Added invoice type checks

faiz_dev
faizatflutter 3 weeks ago
parent 7ec72460e7
commit 34a55396b0

@ -209,7 +209,8 @@ class ApiClientImp implements ApiClient {
} }
body['TokenID'] = "@dm!n"; body['TokenID'] = "@dm!n";
body['PatientID'] = 4774167; // body['PatientID'] = 4770714;
body['PatientID'] = 4771727;
// body['PatientID'] = 89754444; // body['PatientID'] = 89754444;
// body['PatientTypeID'] = 1; // body['PatientTypeID'] = 1;
// body['PatientOutSA'] = 0; // body['PatientOutSA'] = 0;

@ -4,7 +4,7 @@ import 'package:hmg_patient_app_new/core/enums.dart';
class ApiConsts { class ApiConsts {
static const maxSmallScreen = 660; static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
@ -292,7 +292,7 @@ class ApiConsts {
// ************ static values for Api **************** // ************ static values for Api ****************
// static final double appVersionID = 21.2; // static final double appVersionID = 21.2;
static final double appVersionID = 50.7; static final double appVersionID = 21.4;
static final int appChannelId = 3; static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20"; static final String appIpAddress = "10.20.10.20";
static final String appGeneralId = "Cs2020@2016\$2958"; static final String appGeneralId = "Cs2020@2016\$2958";

@ -19,6 +19,10 @@ class GetInvoicesListResponseModel {
String? doctorImageUrl; String? doctorImageUrl;
int? doctorRate; int? doctorRate;
bool? isAllowRefund; bool? isAllowRefund;
int? invoiceType;
String? invoiceTypeDescription;
bool? isPackageInvoice;
bool? isOutPatient;
int? patientNumber; int? patientNumber;
String? projectName; String? projectName;
@ -41,6 +45,10 @@ class GetInvoicesListResponseModel {
this.doctorImageUrl, this.doctorImageUrl,
this.doctorRate, this.doctorRate,
this.isAllowRefund, this.isAllowRefund,
this.invoiceType,
this.invoiceTypeDescription,
this.isPackageInvoice,
this.isOutPatient,
this.patientNumber, this.patientNumber,
this.projectName, this.projectName,
}); });
@ -68,6 +76,10 @@ class GetInvoicesListResponseModel {
doctorImageUrl: json["DoctorImageURL"], doctorImageUrl: json["DoctorImageURL"],
doctorRate: json["DoctorRate"], doctorRate: json["DoctorRate"],
isAllowRefund: json["IsAllowRefund"], isAllowRefund: json["IsAllowRefund"],
invoiceType: json["InvoiceType"],
invoiceTypeDescription: json["InvoiceTypeDescription"],
isPackageInvoice: json["IsPackageInvoice"],
isOutPatient: json['InvoiceType'] != 75,
patientNumber: json["PatientNumber"], patientNumber: json["PatientNumber"],
projectName: json["ProjectName"], projectName: json["ProjectName"],
); );
@ -91,6 +103,10 @@ class GetInvoicesListResponseModel {
"DoctorImageURL": doctorImageUrl, "DoctorImageURL": doctorImageUrl,
"DoctorRate": doctorRate, "DoctorRate": doctorRate,
"IsAllowRefund": isAllowRefund, "IsAllowRefund": isAllowRefund,
"invoiceType": invoiceType,
"invoiceDescription": invoiceTypeDescription,
"isOutPatient": isOutPatient,
"isPackageInvoice": isPackageInvoice,
"PatientNumber": patientNumber, "PatientNumber": patientNumber,
"ProjectName": projectName, "ProjectName": projectName,
}; };

@ -142,6 +142,7 @@ class InvoiceRefundProcedure {
final String? procedureId; final String? procedureId;
final String? procedureName; final String? procedureName;
final String? refundReason; final String? refundReason;
final bool? isApproved;
InvoiceRefundProcedure({ InvoiceRefundProcedure({
this.isLocked, this.isLocked,
@ -150,6 +151,7 @@ class InvoiceRefundProcedure {
this.procedureId, this.procedureId,
this.procedureName, this.procedureName,
this.refundReason, this.refundReason,
this.isApproved,
}); });
factory InvoiceRefundProcedure.fromJson(Map<String, dynamic> json) { factory InvoiceRefundProcedure.fromJson(Map<String, dynamic> json) {
@ -160,6 +162,7 @@ class InvoiceRefundProcedure {
procedureId: json['ProcedureID'] as String?, procedureId: json['ProcedureID'] as String?,
procedureName: json['ProcedureName'] as String?, procedureName: json['ProcedureName'] as String?,
refundReason: json['RefundReason'] as String?, refundReason: json['RefundReason'] as String?,
isApproved: json['IsApproved'] as bool?,
); );
} }
} }

@ -109,6 +109,7 @@ class RefundRequestViewModel extends ChangeNotifier {
currentStep = 0; currentStep = 0;
procedures.clear(); procedures.clear();
needITGApproval = false; needITGApproval = false;
isWholeInvoiceRefund = false;
selectedPaymentMethod = null; selectedPaymentMethod = null;
selectedRefundReason = null; selectedRefundReason = null;
isProceduresLoading = false; isProceduresLoading = false;
@ -208,15 +209,20 @@ class RefundRequestViewModel extends ChangeNotifier {
List<RefundableProcedure> procedures = []; List<RefundableProcedure> procedures = [];
bool isProceduresLoading = false; bool isProceduresLoading = false;
bool needITGApproval = false; bool needITGApproval = false;
bool isWholeInvoiceRefund = false; // For Inpatient/Package invoices
void setProcedures(List<RefundableProcedure> list, {bool needsITGApproval = false}) { void setProcedures(List<RefundableProcedure> list, {bool needsITGApproval = false, bool isWholeInvoiceRefund = false}) {
procedures = list; procedures = list;
needITGApproval = needsITGApproval; needITGApproval = needsITGApproval;
this.isWholeInvoiceRefund = isWholeInvoiceRefund;
isProceduresLoading = false; isProceduresLoading = false;
notifyListeners(); notifyListeners();
} }
void toggleProcedureSelection(RefundableProcedure procedure) { void toggleProcedureSelection(RefundableProcedure procedure) {
// Prevent selection toggle for whole invoice refunds
if (isWholeInvoiceRefund) return;
procedure.isSelected = !procedure.isSelected; procedure.isSelected = !procedure.isSelected;
notifyListeners(); notifyListeners();
} }
@ -229,6 +235,9 @@ class RefundRequestViewModel extends ChangeNotifier {
bool get isAllSelected => procedures.isNotEmpty && procedures.every((p) => p.isSelected); bool get isAllSelected => procedures.isNotEmpty && procedures.every((p) => p.isSelected);
void toggleSelectAll() { void toggleSelectAll() {
// Prevent toggle for whole invoice refunds
if (isWholeInvoiceRefund) return;
final selectAll = !isAllSelected; final selectAll = !isAllSelected;
for (final p in procedures) { for (final p in procedures) {
p.isSelected = selectAll; p.isSelected = selectAll;

@ -24,9 +24,9 @@ import 'package:provider/provider.dart';
class InvoiceListCard extends StatelessWidget { class InvoiceListCard extends StatelessWidget {
final GetInvoicesListResponseModel getInvoicesListResponseModel; final GetInvoicesListResponseModel getInvoicesListResponseModel;
Function? onTap; final Function? onTap;
InvoiceListCard({super.key, required this.getInvoicesListResponseModel, required this.onTap}); const InvoiceListCard({super.key, required this.getInvoicesListResponseModel, required this.onTap});
void _handleRefundInvoiceTap(BuildContext context) { void _handleRefundInvoiceTap(BuildContext context) {
final invoiceNo = getInvoicesListResponseModel.invoiceNo; final invoiceNo = getInvoicesListResponseModel.invoiceNo;
@ -70,7 +70,6 @@ class InvoiceListCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
AppState appState = getIt<AppState>();
return Container( return Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true), decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 20.h, hasShadow: true),
child: Padding( child: Padding(
@ -90,11 +89,14 @@ class InvoiceListCard extends StatelessWidget {
labelText: LocaleKeys.walkin.tr(), labelText: LocaleKeys.walkin.tr(),
textColor: AppColors.textColor, textColor: AppColors.textColor,
), ),
AppCustomChipWidget( if (getInvoicesListResponseModel.invoiceTypeDescription != null &&
labelText: appState.isArabic() ? "العيادات الخارجيه" : "Out Patient", getInvoicesListResponseModel.invoiceTypeDescription!.isNotEmpty) ...[
backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.1), AppCustomChipWidget(
textColor: AppColors.warningColorYellow, labelText: getInvoicesListResponseModel.invoiceTypeDescription ?? "",
), backgroundColor: AppColors.warningColorYellow.withValues(alpha: 0.1),
textColor: AppColors.warningColorYellow,
),
],
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),

@ -74,6 +74,20 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
super.dispose(); super.dispose();
} }
/// Determines if the invoice allows individual procedure selection
/// Returns true for Outpatient and ER invoices only
/// Returns false for Inpatient and Package invoices (whole invoice refund only)
bool get _canSelectIndividualProcedures {
// Package invoices: no individual procedure selection
if (widget.invoice.isPackageInvoice == true) return false;
// Inpatient invoices: no individual procedure selection
if (widget.invoice.isOutPatient == false) return false;
// Outpatient and ER invoices: allow individual procedure selection
return true;
}
void _loadInvoiceDetails() { void _loadInvoiceDetails() {
final invoiceNo = widget.invoice.invoiceNo; final invoiceNo = widget.invoice.invoiceNo;
final projectId = widget.invoice.projectId; final projectId = widget.invoice.projectId;
@ -90,9 +104,17 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
patientPaidAmount: item.patientPaidAmount ?? 0.0, patientPaidAmount: item.patientPaidAmount ?? 0.0,
apiLineItemNo: item.lineItemNo, apiLineItemNo: item.lineItemNo,
apiProcedureId: item.procedureId, apiProcedureId: item.procedureId,
// For Inpatient/Package invoices: auto-select all procedures (can't deselect)
isSelected: !_canSelectIndividualProcedures,
// For Inpatient/Package invoices: set empty string as refund reason (mandatory field)
refundReason: !_canSelectIndividualProcedures ? "Inpatient/Package invoice" : null,
)) ))
.toList(); .toList();
_refundRequestViewModel.setProcedures(procedures, needsITGApproval: details.needITGApproval ?? false); _refundRequestViewModel.setProcedures(
procedures,
needsITGApproval: details.needITGApproval ?? false,
isWholeInvoiceRefund: !_canSelectIndividualProcedures,
);
}, },
); );
} }
@ -123,12 +145,11 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
); );
} }
// Step 1 exactly mirrors RechargeWalletPage hospital row // Step 1 Select Procedures (or whole invoice for Inpatient/Package)
Widget _buildStep1Content(RefundRequestViewModel vm) { Widget _buildStep1Content(RefundRequestViewModel vm) {
return Consumer<RefundRequestViewModel>( return Consumer<RefundRequestViewModel>(
builder: (context, refundVM, _) { builder: (context, refundVM, _) {
final isArabic = _appState.isArabic();
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -164,39 +185,41 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Select All row // Select All row - only show for Outpatient/ER invoices
Material( if (_canSelectIndividualProcedures)
color: Colors.transparent, Material(
child: InkWell( color: Colors.transparent,
onTap: () => _refundRequestViewModel.toggleSelectAll(), child: InkWell(
child: Padding( onTap: () => _refundRequestViewModel.toggleSelectAll(),
padding: EdgeInsets.all(16.h), child: Padding(
child: Row( padding: EdgeInsets.all(16.h),
children: [ child: Row(
SizedBox( children: [
width: 24.w, SizedBox(
height: 24.w, width: 24.w,
child: Transform.scale( height: 24.w,
scale: 24.w / 22, child: Transform.scale(
child: Checkbox( scale: 24.w / 22,
value: vm.isAllSelected, child: Checkbox(
onChanged: (_) => _refundRequestViewModel.toggleSelectAll(), value: vm.isAllSelected,
activeColor: AppColors.primaryRedColor, onChanged: (_) => _refundRequestViewModel.toggleSelectAll(),
side: BorderSide(color: AppColors.checkBoxBorderColor, width: 1), activeColor: AppColors.primaryRedColor,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, side: BorderSide(color: AppColors.checkBoxBorderColor, width: 1),
visualDensity: VisualDensity.compact, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4.r)), visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4.r)),
),
), ),
), ),
), SizedBox(width: 8.w),
SizedBox(width: 8.w), LocaleKeys.selectAll.tr(context: context).toText16(isBold: true),
LocaleKeys.selectAll.tr(context: context).toText16(isBold: true), ],
], ),
), ),
), ),
), ),
), if (_canSelectIndividualProcedures)
Divider(color: AppColors.bottomNAVBorder, height: 1, thickness: 1).paddingSymmetrical(16.w, 0.w), Divider(color: AppColors.bottomNAVBorder, height: 1, thickness: 1).paddingSymmetrical(16.w, 0.w),
...List.generate( ...List.generate(
vm.procedures.length, vm.procedures.length,
(index) => _buildProcedureCard(vm.procedures[index], index, vm.procedures.length), (index) => _buildProcedureCard(vm.procedures[index], index, vm.procedures.length),
@ -331,11 +354,12 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
); );
} }
// Step 2 procedure checkboxes // Procedure Card
Widget _buildProcedureCard(RefundableProcedure procedure, int index, int length) { Widget _buildProcedureCard(RefundableProcedure procedure, int index, int length) {
final isArabic = _appState.isArabic(); final isArabic = _appState.isArabic();
final name = isArabic && procedure.procedureNameN != null ? procedure.procedureNameN! : procedure.procedureName; final name = isArabic && procedure.procedureNameN != null ? procedure.procedureNameN! : procedure.procedureName;
final canSelect = _canSelectIndividualProcedures;
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
@ -349,81 +373,88 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
onTap: () => _refundRequestViewModel.toggleProcedureSelection(procedure), // Disable tap for Inpatient/Package invoices
child: Padding( onTap: canSelect ? () => _refundRequestViewModel.toggleProcedureSelection(procedure) : null,
padding: EdgeInsets.all(16.h), child: Opacity(
child: Column( // Reduce opacity for disabled items
crossAxisAlignment: CrossAxisAlignment.start, opacity: canSelect ? 1.0 : 0.7,
children: [ child: Padding(
Row( padding: EdgeInsets.all(16.h),
crossAxisAlignment: CrossAxisAlignment.center, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
SizedBox( children: [
width: 24.w, Row(
height: 24.w, crossAxisAlignment: CrossAxisAlignment.center,
child: Transform.scale( children: [
scale: 24.w / 22, SizedBox(
child: Checkbox( width: 24.w,
value: procedure.isSelected, height: 24.w,
onChanged: (_) => _refundRequestViewModel.toggleProcedureSelection(procedure), child: Transform.scale(
activeColor: AppColors.primaryRedColor, scale: 24.w / 22,
side: BorderSide(color: AppColors.checkBoxBorderColor, width: 1), child: Checkbox(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, value: procedure.isSelected,
visualDensity: VisualDensity.compact, // Disable checkbox for Inpatient/Package invoices
shape: RoundedRectangleBorder( onChanged: canSelect ? (_) => _refundRequestViewModel.toggleProcedureSelection(procedure) : null,
borderRadius: BorderRadius.circular(4.r), activeColor: AppColors.primaryRedColor,
side: BorderSide(color: AppColors.checkBoxBorderColor, width: 1),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4.r),
),
), ),
), ),
), ),
), SizedBox(width: 8.w),
SizedBox(width: 8.w), Expanded(child: name.toText16(isBold: true)),
Expanded(child: name.toText16(isBold: true)), SizedBox(width: 8.w),
SizedBox(width: 8.w), Utils.getPaymentAmountWithSymbol(
Utils.getPaymentAmountWithSymbol( procedure.patientPaidAmount.toStringAsFixed(2).toText20(
procedure.patientPaidAmount.toStringAsFixed(2).toText20( isBold: true,
isBold: true, isEnglishOnly: true,
isEnglishOnly: true, color: AppColors.textColor,
color: AppColors.textColor,
),
AppColors.textColor,
10.f,
isSaudiCurrency: true,
),
],
),
if (procedure.isSelected) ...[
InkWell(
onTap: () => showRefundReasonBottomSheet(
context,
selectedReason: procedure.refundReason,
onDone: (reason) => _refundRequestViewModel.setRefundReasonForProcedure(procedure, reason),
),
child: Padding(
padding: EdgeInsets.only(top: 16.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.refundReason.tr(context: context).toText12(color: AppColors.greyTextColor, isBold: true),
(procedure.refundReason ?? LocaleKeys.selectRefundReason.tr(context: context))
.toText14(color: AppColors.textColor, isBold: true),
],
), ),
), AppColors.textColor,
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h), 10.f,
], isSaudiCurrency: true,
), ),
), ],
), ),
// Only show refund reason selector for Outpatient/ER invoices
if (canSelect && procedure.isSelected) ...[
InkWell(
onTap: () => showRefundReasonBottomSheet(
context,
selectedReason: procedure.refundReason,
onDone: (reason) => _refundRequestViewModel.setRefundReasonForProcedure(procedure, reason),
),
child: Padding(
padding: EdgeInsets.only(top: 16.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.refundReason.tr(context: context).toText12(color: AppColors.greyTextColor, isBold: true),
(procedure.refundReason ?? LocaleKeys.selectRefundReason.tr(context: context))
.toText14(color: AppColors.textColor, isBold: true),
],
),
),
Utils.buildSvgWithAssets(icon: AppAssets.arrow_down, width: 25.h, height: 25.h),
],
),
),
),
],
if (index != length - 1) ...[
Divider(color: AppColors.bottomNAVBorder, height: 1, thickness: 1).paddingOnly(top: 16.h),
]
], ],
if (index != length - 1) ...[ ),
Divider(color: AppColors.bottomNAVBorder, height: 1, thickness: 1).paddingOnly(top: 16.h),
]
],
), ),
), ),
), ),
@ -492,7 +523,10 @@ class _RefundRequestCreatePageState extends State<RefundRequestCreatePage> {
? (refundRequestViewModel.selectedPaymentMethod == null || ? (refundRequestViewModel.selectedPaymentMethod == null ||
(refundRequestViewModel.selectedPaymentMethod == RefundTabType.invoices && (refundRequestViewModel.selectedPaymentMethod == RefundTabType.invoices &&
(_ibanController.text.trim().isEmpty || _descriptionController.text.trim().isEmpty))) (_ibanController.text.trim().isEmpty || _descriptionController.text.trim().isEmpty)))
: (refundRequestViewModel.selectedProcedures.isEmpty || !refundRequestViewModel.allSelectedProceduresHaveReasons), : (refundRequestViewModel.selectedProcedures.isEmpty ||
// For Outpatient/ER: require refund reasons
// For Inpatient/Package: skip refund reason validation
(_canSelectIndividualProcedures && !refundRequestViewModel.allSelectedProceduresHaveReasons)),
).paddingSymmetrical(24.h, 24.h), ).paddingSymmetrical(24.h, 24.h),
], ],
), ),

@ -186,8 +186,28 @@ class RefundRequestDetailScreen extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
LocaleKeys.procedure.tr(context: context).toText12(color: AppColors.textColor, isBold: true), Expanded(
LocaleKeys.amountOnly.tr(context: context).toText12(color: AppColors.textColor, isBold: true), flex: 3,
child: LocaleKeys.procedure.tr(context: context).toText12(color: AppColors.textColor, isBold: true),
),
SizedBox(width: 8.w),
SizedBox(
width: 70.w,
child: LocaleKeys.approved.tr(context: context).toText12(
color: AppColors.textColor,
isBold: true,
textAlignment: TextAlign.center,
),
),
SizedBox(width: 8.w),
SizedBox(
width: 60.w,
child: LocaleKeys.amountOnly.tr(context: context).toText12(
color: AppColors.textColor,
isBold: true,
textAlignment: TextAlign.end,
),
),
], ],
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
@ -221,6 +241,8 @@ class RefundRequestDetailScreen extends StatelessWidget {
} }
Widget _buildProcedureRow(BuildContext context, InvoiceRefundProcedure procedure) { Widget _buildProcedureRow(BuildContext context, InvoiceRefundProcedure procedure) {
final isApproved = procedure.isApproved ?? false;
return Padding( return Padding(
padding: EdgeInsets.symmetric(vertical: 6.h), padding: EdgeInsets.symmetric(vertical: 6.h),
child: Row( child: Row(
@ -232,7 +254,23 @@ class RefundRequestDetailScreen extends StatelessWidget {
child: (procedure.procedureName ?? '-').toText12(color: AppColors.textColor), child: (procedure.procedureName ?? '-').toText12(color: AppColors.textColor),
), ),
SizedBox(width: 8.w), SizedBox(width: 8.w),
(procedure.patientPaidAmount?.toString() ?? '-').toText12(color: AppColors.textColor, isBold: true), SizedBox(
width: 70.w,
child: (isApproved ? LocaleKeys.yes : LocaleKeys.no).tr(context: context).toText12(
color: AppColors.textColor,
isBold: true,
textAlignment: TextAlign.center,
),
),
SizedBox(width: 8.w),
SizedBox(
width: 60.w,
child: (procedure.patientPaidAmount?.toStringAsFixed(2) ?? '-').toText12(
color: AppColors.textColor,
isBold: true,
textAlignment: TextAlign.end,
),
),
], ],
), ),
); );

Loading…
Cancel
Save