Refund Request and Withdraw Module In Progress!
parent
8aa152f1a0
commit
198280fbde
@ -0,0 +1,7 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="40" height="40" rx="10" fill="#EFEFF0"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0002 9.25C19.2712 9.25 18.6011 9.43823 17.8597 9.76207C17.1407 10.0761 16.307 10.5401 15.2582 11.1238L11.1161 13.4289C10.5397 13.7497 10.0573 14.1526 9.72587 14.6959C9.39281 15.2418 9.25016 15.8673 9.25016 16.5691L9.25008 16.6352C9.24962 16.8906 9.24915 17.1497 9.31072 17.3815C9.46568 17.9648 9.83495 18.3408 10.2872 18.5422C10.6946 18.7238 11.1372 18.75 11.4694 18.75L28.5309 18.75C28.8631 18.75 29.3057 18.7238 29.7131 18.5422C30.1654 18.3408 30.5346 17.9648 30.6896 17.3815C30.7512 17.1497 30.7507 16.8906 30.7502 16.6352L30.7502 16.5691C30.7502 15.8673 30.6075 15.2418 30.2745 14.6959C29.9431 14.1526 29.4607 13.7497 28.8842 13.4289L24.7421 11.1238C23.6934 10.5401 22.8596 10.0761 22.1406 9.76206C21.3992 9.43823 20.7292 9.25 20.0002 9.25ZM19.9961 14C19.4438 14 18.9961 14.4477 18.9961 15C18.9961 15.5523 19.4438 16 19.9961 16H20.0051C20.5574 16 21.0051 15.5523 21.0051 15C21.0051 14.4477 20.5574 14 20.0051 14H19.9961Z" fill="#8F9AA3"/>
|
||||
<path d="M9.25 29.75C9.25 28.0931 10.9289 26.75 13 26.75L27 26.75C29.0711 26.75 30.75 28.0931 30.75 29.75C30.75 30.3023 30.1904 30.75 29.5 30.75L10.5 30.75C9.80964 30.75 9.25 30.3023 9.25 29.75Z" fill="#8F9AA3"/>
|
||||
<path d="M16.3501 25.5H13C12.5865 25.5 12.1848 25.5502 11.8006 25.6448C11.5358 25.71 11.4034 25.7426 11.3268 25.6825C11.2501 25.6224 11.2501 25.4944 11.2501 25.2383V20.216C11.2501 20.2021 11.2501 20.1952 11.2504 20.1904C11.2554 20.0851 11.3352 20.0053 11.4405 20.0002C11.4453 20 11.4534 20 11.4696 20H16.3501C16.5387 20 16.633 20 16.6915 20.0586C16.7501 20.1172 16.7501 20.2114 16.7501 20.4V25.1C16.7501 25.2886 16.7501 25.3828 16.6915 25.4414C16.633 25.5 16.5387 25.5 16.3501 25.5Z" fill="#8F9AA3"/>
|
||||
<path d="M28.1996 25.6448C27.8153 25.5502 27.4135 25.5 27 25.5H23.6501C23.4616 25.5 23.3673 25.5 23.3087 25.4414C23.2501 25.3828 23.2501 25.2886 23.2501 25.1V20.4C23.2501 20.2114 23.2501 20.1172 23.3087 20.0586C23.3673 20 23.4616 20 23.6501 20L28.531 20C28.5469 20 28.5548 20 28.5595 20.0002C28.665 20.0052 28.745 20.0851 28.7499 20.1906L28.7501 20.1994L28.7501 20.2157V25.2384C28.7501 25.4945 28.7501 25.6226 28.6735 25.6826C28.5968 25.7427 28.4644 25.7101 28.1996 25.6448Z" fill="#8F9AA3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,7 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="40" height="40" rx="10" fill="#EFEFF0"/>
|
||||
<path d="M11 10C10.4477 10 10 10.4477 10 11C10 11.5523 10.4477 12 11 12L19 12C19.5523 12 20 11.5523 20 11C20 10.4477 19.5523 10 19 10L11 10Z" fill="#8F9AA3"/>
|
||||
<path d="M11 16C10.4477 16 10 16.4477 10 17C10 17.5523 10.4477 18 11 18H19C19.5523 18 20 17.5523 20 17C20 16.4477 19.5523 16 19 16L11 16Z" fill="#8F9AA3"/>
|
||||
<path d="M10 23C10 22.4477 10.4477 22 11 22L29 22C29.5523 22 30 22.4477 30 23C30 23.5523 29.5523 24 29 24L11 24C10.4477 24 10 23.5523 10 23Z" fill="#8F9AA3"/>
|
||||
<path d="M11 28C10.4477 28 10 28.4477 10 29C10 29.5523 10.4477 30 11 30L29 30C29.5523 30 30 29.5523 30 29C30 28.4477 29.5523 28 29 28L11 28Z" fill="#8F9AA3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 790 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,4 @@
|
||||
<svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.93712 2.78621e-06C4.05309 -5.24077e-05 3.28757 -0.00010021 2.67381 0.0856193C2.01162 0.178101 1.38072 0.387107 0.873027 0.91449C0.370475 1.43654 0.176225 2.07619 0.0895854 2.74561C0.00806761 3.37545 0.00810474 4.16382 0.00814813 5.08738L0.00815016 5.15177C0.00815016 5.40552 0.00591272 5.64931 0.00378245 5.88142C-0.00173354 6.48244 -0.00653088 7.00515 0.0300965 7.41981C0.0870866 8.06499 0.254658 8.66564 0.762836 9.19353C1.14586 9.59142 1.77891 9.60346 2.17679 9.22044C2.57468 8.83741 2.58672 8.20436 2.2037 7.80648C2.12657 7.72636 2.05658 7.63147 2.02234 7.24383C1.99474 6.93135 1.99819 6.55852 2.00318 6.02087C2.0055 5.77045 2.00815 5.48426 2.00815 5.15177C2.00815 4.14595 2.01012 3.48847 2.07304 3.00232C2.13273 2.54115 2.23113 2.38751 2.31389 2.30154C2.39151 2.22092 2.52427 2.12592 2.95045 2.06639C3.40942 2.00229 4.0335 2.00001 5.00488 2.00001L16.9951 2.00001C17.9664 2.00001 18.5905 2.00229 19.0495 2.0664C19.4757 2.12592 19.6084 2.22092 19.686 2.30155C19.7688 2.38751 19.8672 2.54115 19.9269 3.00232C19.9898 3.48847 19.9918 4.14595 19.9918 5.15177C19.9918 5.48233 19.9944 5.76713 19.9967 6.01653C20.0016 6.55612 20.005 6.93046 19.9773 7.2435C19.9429 7.63104 19.8729 7.72616 19.7956 7.80648C19.4125 8.20436 19.4246 8.83741 19.8225 9.22044C20.2203 9.60346 20.8534 9.59142 21.2364 9.19353C21.7444 8.66584 21.9123 8.06542 21.9695 7.42014C22.0063 7.00455 22.0016 6.48073 21.9961 5.87825C21.994 5.64711 21.9918 5.40439 21.9918 5.15177L21.9918 5.08739C21.9918 4.16387 21.9919 3.37543 21.9103 2.74561C21.8237 2.07619 21.6295 1.43654 21.1269 0.914491C20.6192 0.387108 19.9883 0.178102 19.3261 0.0856201C18.7124 -9.94951e-05 17.9468 -5.18116e-05 17.0628 3.38225e-06L4.93712 2.78621e-06Z" fill="#0B85F7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.1978 4C13.9586 3.99998 14.598 3.99996 15.1143 4.06403C15.6617 4.13197 16.1602 4.2806 16.5912 4.64146C17.0222 5.00232 17.2562 5.46697 17.4193 5.99389C17.5731 6.49084 17.6855 7.1203 17.8192 7.8693L18.4895 11.6226C18.7725 13.2078 18.9993 14.4775 19.0348 15.4829C19.0715 16.5216 18.9118 17.4176 18.2925 18.1573C17.6731 18.8971 16.8191 19.2118 15.7902 19.3582C14.7942 19.5 13.5044 19.5 11.8942 19.5H10.1065C8.49624 19.5 7.20645 19.5 6.21049 19.3582C5.18153 19.2118 4.32758 18.8971 3.70822 18.1573C3.08886 17.4176 2.92921 16.5216 2.96588 15.4829C3.00137 14.4775 3.22812 13.2078 3.51121 11.6227L4.18145 7.86934C4.31517 7.12034 4.42756 6.49084 4.58139 5.99389C4.74449 5.46697 4.97845 5.00232 5.40946 4.64146C5.84047 4.2806 6.339 4.13197 6.8864 4.06403C7.40264 3.99996 8.04206 3.99998 8.80289 4L13.1978 4ZM11 7.5C11.4142 7.5 11.75 7.83579 11.75 8.25L11.75 13.4393L12.9697 12.2197C13.2626 11.9268 13.7374 11.9268 14.0303 12.2197C14.3232 12.5126 14.3232 12.9874 14.0303 13.2803L11.5303 15.7803C11.2374 16.0732 10.7626 16.0732 10.4697 15.7803L7.96967 13.2803C7.67678 12.9874 7.67678 12.5126 7.96967 12.2197C8.26256 11.9268 8.73744 11.9268 9.03033 12.2197L10.25 13.4393L10.25 8.25C10.25 7.83579 10.5858 7.5 11 7.5Z" fill="#0B85F7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@ -0,0 +1,5 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="40" height="40" rx="10" fill="#EFEFF0"/>
|
||||
<path d="M26.5 15.5C26.5 16.6046 25.6046 17.5 24.5 17.5C23.3954 17.5 22.5 16.6046 22.5 15.5C22.5 14.3954 23.3954 13.5 24.5 13.5C25.6046 13.5 26.5 14.3954 26.5 15.5Z" fill="#8F9AA3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.9255 9.5H20.0745C22.2504 9.49998 23.9852 9.49996 25.3453 9.68282C26.7497 9.87164 27.9035 10.2717 28.8159 11.1841C29.7283 12.0965 30.1284 13.2503 30.3172 14.6547C30.5 16.0149 30.5 17.7496 30.5 19.9256V20.0744C30.5 22.2504 30.5 23.9851 30.3172 25.3453C30.1284 26.7497 29.7283 27.9035 28.8159 28.8159C27.9035 29.7283 26.7497 30.1284 25.3453 30.3172C23.9851 30.5 22.2504 30.5 20.0744 30.5H19.9256C17.7496 30.5 16.0149 30.5 14.6547 30.3172C13.2503 30.1284 12.0965 29.7283 11.1841 28.8159C10.2717 27.9035 9.87164 26.7497 9.68282 25.3453C9.49996 23.9852 9.49998 22.2504 9.5 20.0745V19.9255C9.49998 17.7496 9.49996 16.0148 9.68282 14.6547C9.87164 13.2503 10.2717 12.0965 11.1841 11.1841C12.0965 10.2717 13.2503 9.87164 14.6547 9.68282C16.0148 9.49996 17.7496 9.49998 19.9255 9.5ZM14.9212 11.665C13.7386 11.824 13.0772 12.1195 12.5984 12.5984C12.1195 13.0772 11.824 13.7386 11.665 14.9212C11.5021 16.1326 11.5 17.7326 11.5 20C11.5 20.2688 11.5 20.5282 11.5004 20.7786C11.7879 20.7608 12.0762 20.7521 12.3647 20.7527C15.1778 20.6952 17.9275 21.572 20.124 23.2364C21.9124 24.5915 23.2416 26.3991 23.9596 28.4377C24.3674 28.4138 24.7385 28.3808 25.0788 28.335C25.2221 28.3157 25.3578 28.2945 25.4864 28.2711C24.9795 26.6882 24.1544 25.2258 23.0687 23.9582C22.8393 23.6904 22.9291 23.27 23.2648 23.1622C24.122 22.887 24.9998 22.7468 25.8878 22.7501C26.7607 22.7494 27.6259 22.889 28.4723 23.162C28.4994 22.2767 28.5 21.2378 28.5 20C28.5 17.7326 28.4979 16.1326 28.335 14.9212C28.176 13.7386 27.8805 13.0772 27.4017 12.5984C26.9228 12.1195 26.2614 11.824 25.0788 11.665C23.8674 11.5021 22.2674 11.5 20 11.5C17.7326 11.5 16.1326 11.5021 14.9212 11.665Z" fill="#8F9AA3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@ -1 +1,99 @@
|
||||
class SubmitRefundProcedureItem {
|
||||
final int lineItemNo;
|
||||
final String procedureId;
|
||||
final String procedureName;
|
||||
final double patientPaidAmount;
|
||||
final String refundReason;
|
||||
|
||||
const SubmitRefundProcedureItem({
|
||||
required this.lineItemNo,
|
||||
required this.procedureId,
|
||||
required this.procedureName,
|
||||
required this.patientPaidAmount,
|
||||
required this.refundReason,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"LineItemNo": lineItemNo,
|
||||
"ProcedureID": procedureId,
|
||||
"ProcedureName": procedureName,
|
||||
"PatientPaidAmount": patientPaidAmount,
|
||||
"RefundReason": refundReason,
|
||||
};
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SubmitRefundProcedureItem{lineItemNo: $lineItemNo, procedureId: $procedureId, procedureName: $procedureName, patientPaidAmount: $patientPaidAmount, refundReason: $refundReason}';
|
||||
}
|
||||
}
|
||||
|
||||
class SubmitRefundRequestModel {
|
||||
final int projectId;
|
||||
final String refundType;
|
||||
final String refundProject;
|
||||
final int refundProjectId;
|
||||
final String refundPatientId;
|
||||
final String patientMobileNumber;
|
||||
final String refundPatientName;
|
||||
final String refundNationalId;
|
||||
final String refundInvoiceNo;
|
||||
final String refundAppointmentNo;
|
||||
final int refundDoctorId;
|
||||
final String refundDoctorName;
|
||||
final int refundClinicId;
|
||||
final String refundClinicName;
|
||||
final String refundDestination;
|
||||
final String refundIban;
|
||||
final String refundRemarks;
|
||||
final double refundTotalAmount;
|
||||
final List<SubmitRefundProcedureItem> refundProceduresList;
|
||||
|
||||
const SubmitRefundRequestModel({
|
||||
required this.projectId,
|
||||
required this.refundType,
|
||||
required this.refundProject,
|
||||
required this.refundProjectId,
|
||||
required this.refundPatientId,
|
||||
required this.patientMobileNumber,
|
||||
required this.refundPatientName,
|
||||
required this.refundNationalId,
|
||||
required this.refundInvoiceNo,
|
||||
required this.refundAppointmentNo,
|
||||
required this.refundDoctorId,
|
||||
required this.refundDoctorName,
|
||||
required this.refundClinicId,
|
||||
required this.refundClinicName,
|
||||
required this.refundDestination,
|
||||
required this.refundIban,
|
||||
required this.refundRemarks,
|
||||
required this.refundTotalAmount,
|
||||
required this.refundProceduresList,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"ProjectID": projectId,
|
||||
"Refund_RefundType": refundType,
|
||||
"Refund_Project": refundProject,
|
||||
"Refund_ProjectId": refundProjectId,
|
||||
"Refund_PatientId": refundPatientId,
|
||||
"PatientMobileNumber": patientMobileNumber,
|
||||
"Refund_PatientName": refundPatientName,
|
||||
"Refund_NationalId": refundNationalId,
|
||||
"Refund_InvoiceNo": refundInvoiceNo,
|
||||
"Refund_AppointmentNo": refundAppointmentNo,
|
||||
"Refund_DoctorId": refundDoctorId,
|
||||
"Refund_DoctorName": refundDoctorName,
|
||||
"Refund_ClinicId": refundClinicId,
|
||||
"Refund_ClinicName": refundClinicName,
|
||||
"Refund_RefundDestination": refundDestination,
|
||||
"Refund_IBAN": refundIban,
|
||||
"Refund_Remarks": refundRemarks,
|
||||
"Refund_TotalRefundAmount": refundTotalAmount,
|
||||
"Refund_ProceduresList": refundProceduresList.map((p) => p.toJson()).toList(),
|
||||
};
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SubmitRefundRequestModel{projectId: $projectId, refundType: $refundType, refundProject: $refundProject, refundProjectId: $refundProjectId, refundPatientId: $refundPatientId, patientMobileNumber: $patientMobileNumber, refundPatientName: $refundPatientName, refundNationalId: $refundNationalId, refundInvoiceNo: $refundInvoiceNo, refundAppointmentNo: $refundAppointmentNo, refundDoctorId: $refundDoctorId, refundDoctorName: $refundDoctorName, refundClinicId: $refundClinicId, refundClinicName: $refundClinicName, refundDestination: $refundDestination, refundIban: $refundIban, refundRemarks: $refundRemarks, refundTotalAmount: $refundTotalAmount, refundProceduresList: $refundProceduresList}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1 +1,92 @@
|
||||
class SubmitRefundResponseModel {
|
||||
final String? message;
|
||||
final String? refundType;
|
||||
final String? patientId;
|
||||
final String? refNo;
|
||||
|
||||
SubmitRefundResponseModel({
|
||||
this.message,
|
||||
this.refundType,
|
||||
this.patientId,
|
||||
this.refNo,
|
||||
});
|
||||
|
||||
factory SubmitRefundResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
return SubmitRefundResponseModel(
|
||||
message: json['message'] as String?,
|
||||
refundType: json['refundType'] as String?,
|
||||
patientId: json['patientId']?.toString(),
|
||||
refNo: json['refNo']?.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RefundStatusModel {
|
||||
final String? errorMessage;
|
||||
final String? lastUpdated;
|
||||
final bool? pendingVerification;
|
||||
final String? referenceNumber;
|
||||
final String? requestStatusName;
|
||||
final String? status;
|
||||
final bool? verified;
|
||||
|
||||
RefundStatusModel({
|
||||
this.errorMessage,
|
||||
this.lastUpdated,
|
||||
this.pendingVerification,
|
||||
this.referenceNumber,
|
||||
this.requestStatusName,
|
||||
this.status,
|
||||
this.verified,
|
||||
});
|
||||
|
||||
factory RefundStatusModel.fromJson(Map<String, dynamic> json) {
|
||||
return RefundStatusModel(
|
||||
errorMessage: json['ErrorMessage'] as String?,
|
||||
lastUpdated: json['LastUpdated'] as String?,
|
||||
pendingVerification: json['PendingVerification'] as bool?,
|
||||
referenceNumber: json['ReferenceNumber'] as String?,
|
||||
requestStatusName: json['RequestStatusName'] as String?,
|
||||
status: json['Status'] as String?,
|
||||
verified: json['Verified'] as bool?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RefundInvoiceModel {
|
||||
final String? invoiceNumber;
|
||||
final String? invoiceDate;
|
||||
final double? totalAmount;
|
||||
final double? patientShare;
|
||||
final String? clinicName;
|
||||
final String? clinicNameN;
|
||||
final int? projectId;
|
||||
final String? projectName;
|
||||
final String? projectNameN;
|
||||
|
||||
RefundInvoiceModel({
|
||||
this.invoiceNumber,
|
||||
this.invoiceDate,
|
||||
this.totalAmount,
|
||||
this.patientShare,
|
||||
this.clinicName,
|
||||
this.clinicNameN,
|
||||
this.projectId,
|
||||
this.projectName,
|
||||
this.projectNameN,
|
||||
});
|
||||
|
||||
factory RefundInvoiceModel.fromJson(Map<String, dynamic> json) {
|
||||
return RefundInvoiceModel(
|
||||
invoiceNumber: json['InvoiceNumber'] as String?,
|
||||
invoiceDate: json['InvoiceDate'] as String?,
|
||||
totalAmount: (json['TotalAmount'] as num?)?.toDouble(),
|
||||
patientShare: (json['PatientShare'] as num?)?.toDouble(),
|
||||
clinicName: json['ClinicName'] as String?,
|
||||
clinicNameN: json['ClinicNameN'] as String?,
|
||||
projectId: json['ProjectID'] as int?,
|
||||
projectName: json['ProjectName'] as String?,
|
||||
projectNameN: json['ProjectNameN'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,325 @@
|
||||
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/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/habib_wallet/habib_wallet_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/habib_wallet/widgets/select_hospital_bottom_sheet.dart';
|
||||
import 'package:hmg_patient_app_new/presentation/refund_request/refund_history_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/image_picker.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class WithdrawRequestCreatePage extends StatefulWidget {
|
||||
const WithdrawRequestCreatePage({super.key});
|
||||
|
||||
@override
|
||||
State<WithdrawRequestCreatePage> createState() => _WithdrawRequestCreatePageState();
|
||||
}
|
||||
|
||||
class _WithdrawRequestCreatePageState extends State<WithdrawRequestCreatePage> {
|
||||
late HabibWalletViewModel _habibWalletViewModel;
|
||||
late AppState _appState;
|
||||
|
||||
final TextEditingController _bankDetailsController = TextEditingController();
|
||||
final TextEditingController _descriptionController = TextEditingController();
|
||||
final FocusNode _ibanFocusNode = FocusNode();
|
||||
final FocusNode _descriptionFocusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_appState = getIt.get<AppState>();
|
||||
_habibWalletViewModel = context.read<HabibWalletViewModel>();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_habibWalletViewModel.getProjectsList();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_bankDetailsController.dispose();
|
||||
_descriptionController.dispose();
|
||||
_ibanFocusNode.dispose();
|
||||
_descriptionFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool get _isFormValid {
|
||||
final vm = _habibWalletViewModel;
|
||||
return vm.selectedHospital != null &&
|
||||
!vm.isAdvancesLoading &&
|
||||
_bankDetailsController.text.trim().isNotEmpty &&
|
||||
_descriptionController.text.trim().isNotEmpty;
|
||||
}
|
||||
|
||||
// ── Bottom bar ────────────────────────────────────────────────────────────
|
||||
|
||||
Widget _buildBottomBar() {
|
||||
return Consumer<HabibWalletViewModel>(
|
||||
builder: (context, vm, _) {
|
||||
final isValid = vm.selectedHospital != null &&
|
||||
!vm.isAdvancesLoading &&
|
||||
_bankDetailsController.text.trim().isNotEmpty &&
|
||||
_descriptionController.text.trim().isNotEmpty;
|
||||
|
||||
return Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.r,
|
||||
hasShadow: true,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CustomButton(
|
||||
text: LocaleKeys.submitRequest.tr(context: context),
|
||||
isDisabled: !isValid,
|
||||
onPressed: () {
|
||||
final isFormValid = vm.validateWithdrawForm(
|
||||
iban: _bankDetailsController.text,
|
||||
description: _descriptionController.text,
|
||||
);
|
||||
if (isFormValid) {
|
||||
// TODO: Submit withdraw request
|
||||
}
|
||||
},
|
||||
).paddingSymmetrical(24.h, 24.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProjectSelectionAndBalance(HabibWalletViewModel habibWalletViewModel) {
|
||||
final isArabic = _appState.isArabic();
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.select_hospital_icon,
|
||||
width: 40.h,
|
||||
height: 40.h,
|
||||
applyThemeColor: false,
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
LocaleKeys.hospital.tr(context: context).toText12(color: AppColors.greyTextColor, isBold: true),
|
||||
(habibWalletViewModel.selectedHospital != null
|
||||
? ((isArabic
|
||||
? (habibWalletViewModel.selectedHospital!.nameN?.toString() ?? habibWalletViewModel.selectedHospital!.name)
|
||||
: habibWalletViewModel.selectedHospital!.name) ??
|
||||
LocaleKeys.selectHospital.tr(context: context))
|
||||
: LocaleKeys.selectHospital.tr(context: context))
|
||||
.toText14(color: AppColors.textColor, isBold: true),
|
||||
]),
|
||||
],
|
||||
),
|
||||
Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.arrow_down,
|
||||
width: 25.h,
|
||||
height: 25.h,
|
||||
),
|
||||
],
|
||||
).onPress(() {
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
title: LocaleKeys.selectHospital.tr(context: context),
|
||||
isDismissible: false,
|
||||
child: SelectHospitalBottomSheet(
|
||||
onHospitalSelected: (hospital) {
|
||||
habibWalletViewModel.setSelectedHospital(hospital);
|
||||
habibWalletViewModel.fetchAdvancesForHospital();
|
||||
},
|
||||
),
|
||||
callBackFunc: () {},
|
||||
);
|
||||
}),
|
||||
// Only show divider + amount once hospital is selected
|
||||
if (habibWalletViewModel.selectedHospital != null) ...[
|
||||
Divider(color: AppColors.bottomNAVBorder, thickness: 1).paddingOnly(top: 16.h),
|
||||
habibWalletViewModel.isAdvancesLoading
|
||||
? Container(
|
||||
height: 60.h,
|
||||
// width: 160.w,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
),
|
||||
).toShimmer2(isShow: true, radius: 12.r)
|
||||
: Utils.getPaymentAmountWithSymbol(
|
||||
habibWalletViewModel.totalAdvancesBalance.toStringAsFixed(2).toText44(isBold: true),
|
||||
AppColors.blackColor,
|
||||
18.w,
|
||||
isSaudiCurrency: true,
|
||||
isExpanded: false,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBankInputDetails() {
|
||||
return Consumer<HabibWalletViewModel>(
|
||||
builder: (context, viewModel, _) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
|
||||
child: Column(
|
||||
children: [
|
||||
TextInputWidget(
|
||||
labelText: LocaleKeys.addIbanDetails.tr(),
|
||||
hintText: "SA0000000000000000000000",
|
||||
controller: _bankDetailsController,
|
||||
focusNode: _ibanFocusNode,
|
||||
leadingIconNeedsContainer: false,
|
||||
autoFocus: false,
|
||||
keyboardType: TextInputType.text,
|
||||
isEnable: true,
|
||||
isReadOnly: false,
|
||||
prefix: null,
|
||||
isBorderAllowed: false,
|
||||
isAllowLeadingIcon: true,
|
||||
fontSize: 14.f,
|
||||
isCountryDropDown: false,
|
||||
leadingIcon: AppAssets.bankIcon,
|
||||
fontFamily: "Poppins",
|
||||
hasError: viewModel.ibanError != null,
|
||||
errorMessage: viewModel.ibanError,
|
||||
onChange: (value) {
|
||||
viewModel.clearIbanError();
|
||||
},
|
||||
onSubmitted: (value) {
|
||||
_descriptionFocusNode.requestFocus();
|
||||
},
|
||||
),
|
||||
Divider(color: AppColors.bottomNAVBorder, thickness: 1).withVerticalPadding(16.h),
|
||||
TextInputWidget(
|
||||
labelText: LocaleKeys.description.tr(),
|
||||
hintText: LocaleKeys.enterDescription.tr(),
|
||||
controller: _descriptionController,
|
||||
focusNode: _descriptionFocusNode,
|
||||
autoFocus: false,
|
||||
keyboardType: TextInputType.text,
|
||||
leadingIconNeedsContainer: false,
|
||||
isEnable: true,
|
||||
isReadOnly: false,
|
||||
prefix: null,
|
||||
isBorderAllowed: false,
|
||||
isAllowLeadingIcon: true,
|
||||
fontSize: 14.f,
|
||||
isCountryDropDown: false,
|
||||
leadingIcon: AppAssets.descriptionIcon,
|
||||
fontFamily: "Poppins",
|
||||
hasError: viewModel.withdrawDescriptionError != null,
|
||||
errorMessage: viewModel.withdrawDescriptionError,
|
||||
onChange: (value) {
|
||||
viewModel.clearWithdrawDescriptionError();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildImagePickerDropDown() {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16.h),
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.selectImageIcon,
|
||||
width: 40.h,
|
||||
height: 40.h,
|
||||
applyThemeColor: false,
|
||||
),
|
||||
SizedBox(width: 8.h),
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
LocaleKeys.uploadImage.tr(context: context).toText12(color: AppColors.greyTextColor, isBold: true),
|
||||
LocaleKeys.selectImage.tr(context: context).toText14(color: AppColors.textColor, isBold: true),
|
||||
]),
|
||||
],
|
||||
),
|
||||
Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.arrow_down,
|
||||
width: 25.h,
|
||||
height: 25.h,
|
||||
),
|
||||
],
|
||||
).onPress(() {
|
||||
ImageOptions.showImageOptionsNew(
|
||||
context,
|
||||
false,
|
||||
title: LocaleKeys.selectOptions.tr(context: context),
|
||||
(String image, File file) {},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// ── Build ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<HabibWalletViewModel>(
|
||||
builder: (context, habibWalletViewModel, _) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgScaffoldColor,
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CollapsingListView(
|
||||
title: LocaleKeys.requestRefund.tr(context: context),
|
||||
requests: () => Navigator.of(context).push(CustomPageRoute(page: RefundHistoryScreen())),
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.only(bottom: 32.h, left: 24.w, right: 24.w),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildProjectSelectionAndBalance(habibWalletViewModel),
|
||||
if (habibWalletViewModel.selectedHospital != null) ...[
|
||||
SizedBox(height: 16.h),
|
||||
_buildBankInputDetails(),
|
||||
SizedBox(height: 16.h),
|
||||
_buildImagePickerDropDown(),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildBottomBar(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
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/widget_extensions.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/radio_list_tile_widget.dart';
|
||||
|
||||
void showRefundReasonBottomSheet(
|
||||
BuildContext context, {
|
||||
required String? selectedReason,
|
||||
required ValueChanged<String> onDone,
|
||||
}) {
|
||||
showCommonBottomSheetWithoutHeight(
|
||||
context,
|
||||
title: LocaleKeys.selectRefundReason.tr(context: context),
|
||||
isDismissible: true,
|
||||
child: _RefundReasonSheetContent(
|
||||
selectedReason: selectedReason,
|
||||
onDone: onDone,
|
||||
),
|
||||
callBackFunc: () {},
|
||||
);
|
||||
}
|
||||
|
||||
class _RefundReasonSheetContent extends StatefulWidget {
|
||||
final String? selectedReason;
|
||||
final ValueChanged<String> onDone;
|
||||
|
||||
const _RefundReasonSheetContent({
|
||||
required this.selectedReason,
|
||||
required this.onDone,
|
||||
});
|
||||
|
||||
@override
|
||||
State<_RefundReasonSheetContent> createState() => _RefundReasonSheetContentState();
|
||||
}
|
||||
|
||||
class _RefundReasonSheetContentState extends State<_RefundReasonSheetContent> {
|
||||
String? _selected;
|
||||
|
||||
static List<String> _reasons(BuildContext context) => [
|
||||
LocaleKeys.refundReason1.tr(context: context),
|
||||
LocaleKeys.refundReason2.tr(context: context),
|
||||
LocaleKeys.refundReason3.tr(context: context),
|
||||
LocaleKeys.refundReason4.tr(context: context),
|
||||
LocaleKeys.refundReason5.tr(context: context),
|
||||
LocaleKeys.refundReason6.tr(context: context),
|
||||
LocaleKeys.refundReason7.tr(context: context),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selected = widget.selectedReason;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final reasons = _reasons(context);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 24.r,
|
||||
hasShadow: false,
|
||||
),
|
||||
child: ListView.separated(
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: reasons.length,
|
||||
separatorBuilder: (_, __) => Divider(
|
||||
color: AppColors.bottomNAVBorder,
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
).paddingSymmetrical(16.w, 0.w),
|
||||
itemBuilder: (context, index) {
|
||||
final reason = reasons[index];
|
||||
return RadioListTileWidget<String>(
|
||||
value: reason,
|
||||
groupValue: _selected,
|
||||
title: reason,
|
||||
onChanged: (value) {
|
||||
if (value != null) setState(() => _selected = value);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
CustomButton(
|
||||
text: LocaleKeys.done.tr(context: context),
|
||||
isDisabled: _selected == null,
|
||||
onPressed: () {
|
||||
if (_selected != null) {
|
||||
widget.onDone(_selected!);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
).paddingSymmetrical(0, 0),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue