From 603e7ee7e5bab13e887f397d1c409f02e13f95dc Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Fri, 21 Nov 2025 16:57:37 +0530 Subject: [PATCH] feat: add advance payment indicator in payment request screens and improve code formatting --- .../payment_request_detail_screen.dart | 101 ++++++++++++------ lib/view/finance/payment_request_screen.dart | 25 ++++- 2 files changed, 94 insertions(+), 32 deletions(-) diff --git a/lib/view/finance/payment_request_detail_screen.dart b/lib/view/finance/payment_request_detail_screen.dart index dfc3b87..1dc3720 100644 --- a/lib/view/finance/payment_request_detail_screen.dart +++ b/lib/view/finance/payment_request_detail_screen.dart @@ -26,7 +26,7 @@ class PaymentRequestDetailScreen extends StatefulWidget { final String paymentRequestId; const PaymentRequestDetailScreen({super.key, required this.paymentRequestId}); - @override + @override State createState() => _PaymentRequestDetailScreenState(); } @@ -119,8 +119,9 @@ class _PaymentRequestDetailScreenState extends State final request = controller.paymentRequest.value; - if ((controller.errorMessage.value ).isNotEmpty) { - return Center(child: MyText.bodyMedium(controller.errorMessage.value)); + if ((controller.errorMessage.value).isNotEmpty) { + return Center( + child: MyText.bodyMedium(controller.errorMessage.value)); } if (request == null) { @@ -152,7 +153,8 @@ class _PaymentRequestDetailScreenState extends State request: request, colorParser: _parseColor, employeeInfo: employeeInfo, - onEdit: () => _openEditPaymentRequestBottomSheet(request), + onEdit: () => + _openEditPaymentRequestBottomSheet(request), ), const Divider(height: 30, thickness: 1.2), _Logs( @@ -272,8 +274,7 @@ class _PaymentRequestDetailScreenState extends State message: success ? 'Status updated successfully' : 'Failed to update status', - type: - success ? SnackbarType.success : SnackbarType.error, + type: success ? SnackbarType.success : SnackbarType.error, ); if (success) await controller.fetchPaymentRequestDetail(); @@ -323,8 +324,8 @@ class _PaymentRequestDetailScreenState extends State ), MySpacing.height(2), GetBuilder(builder: (_) { - final name = - projectController.selectedProject?.name ?? 'Select Project'; + final name = projectController.selectedProject?.name ?? + 'Select Project'; return Row( children: [ const Icon(Icons.work_outline, @@ -410,10 +411,35 @@ class _HeaderState extends State<_Header> with UIMixin { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - MyText.bodyMedium( - 'ID: ${widget.request.paymentRequestUID ?? '-'}', - fontWeight: 700, - fontSize: 14, + Row( + children: [ + MyText.bodyMedium( + 'ID: ${widget.request.paymentRequestUID ?? '-'}', + fontWeight: 700, + fontSize: 14, + ), + + // 🔥 ADVANCE CHIP — show only if true + if (widget.request.isAdvancePayment == true) ...[ + const SizedBox(width: 8), + Container( + padding: + const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.orange.shade700, + borderRadius: BorderRadius.circular(4), + ), + child: const Text( + 'ADVANCE', + style: TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ], ), if (canEdit) IconButton( @@ -513,17 +539,17 @@ class _Logs extends StatelessWidget { final last = updatedBy?.lastName ?? ''; final initials = '${first.isNotEmpty ? first[0] : ''}${last.isNotEmpty ? last[0] : ''}'; - final name = ((first + ' ' + last).trim().isNotEmpty) - ? '$first $last' - : '-'; + final name = + ((first + ' ' + last).trim().isNotEmpty) ? '$first $last' : '-'; final updatedAt = log.updatedAt; final timeAgo = (updatedAt != null) - ? timeago.format(updatedAt.toUtc().add(const Duration(hours: 5, minutes: 30))) + ? timeago.format(updatedAt + .toUtc() + .add(const Duration(hours: 5, minutes: 30))) : '-'; - final nextStatusColor = - colorParser(log.nextStatus?.color ?? ''); + final nextStatusColor = colorParser(log.nextStatus?.color ?? ''); return TimelineTile( alignment: TimelineAlign.start, @@ -667,14 +693,18 @@ class _DetailsTable extends StatelessWidget { _labelValueRow("Transaction ID:", request.paidTransactionId ?? ''), _labelValueRow("Payee:", request.payee ?? '-'), _labelValueRow("Project:", request.project?.name ?? '-'), - _labelValueRow("Expense Category:", request.expenseCategory?.name ?? '-'), + _labelValueRow( + "Expense Category:", request.expenseCategory?.name ?? '-'), // Amounts - _labelValueRow("Amount:", _formatCurrencyAmount(currencySymbol, request.amount)), + _labelValueRow( + "Amount:", _formatCurrencyAmount(currencySymbol, request.amount)), if (request.baseAmount != null) - _labelValueRow("Base Amount:", _formatCurrencyAmount(currencySymbol, request.baseAmount)), + _labelValueRow("Base Amount:", + _formatCurrencyAmount(currencySymbol, request.baseAmount)), if (request.taxAmount != null) - _labelValueRow("Tax Amount:", _formatCurrencyAmount(currencySymbol, request.taxAmount)), + _labelValueRow("Tax Amount:", + _formatCurrencyAmount(currencySymbol, request.taxAmount)), if (request.expenseCategory?.noOfPersonsRequired == true) _labelValueRow("Additional Persons Required:", "Yes"), if (request.expenseCategory?.isAttachmentRequried == true) @@ -706,27 +736,36 @@ class _DetailsTable extends StatelessWidget { format: 'dd MMM yyyy'), ), if (request.paidBy != null) - _labelValueRow("Paid By:", "${request.paidBy?.firstName ?? ''} ${request.paidBy?.lastName ?? ''}".trim()), + _labelValueRow( + "Paid By:", + "${request.paidBy?.firstName ?? ''} ${request.paidBy?.lastName ?? ''}" + .trim()), // Flags - _labelValueRow( - "Advance Payment:", (request.isAdvancePayment ?? false) ? "Yes" : "No"), - _labelValueRow( - "Expense Created:", (request.isExpenseCreated ?? false) ? "Yes" : "No"), + _labelValueRow("Advance Payment:", + (request.isAdvancePayment ?? false) ? "Yes" : "No"), + _labelValueRow("Expense Created:", + (request.isExpenseCreated ?? false) ? "Yes" : "No"), _labelValueRow("Active:", (request.isActive ?? false) ? "Yes" : "No"), // Recurring Payment Info if (request.recurringPayment != null) ...[ const SizedBox(height: 6), MyText.bodySmall("Recurring Payment Info:", fontWeight: 600), - _labelValueRow("Recurring ID:", request.recurringPayment?.recurringPaymentUID ?? '-'), - _labelValueRow("Amount:", _formatCurrencyAmount(currencySymbol, request.recurringPayment?.amount)), - _labelValueRow("Variable Amount:", (request.recurringPayment?.isVariable ?? false) ? "Yes" : "No"), + _labelValueRow("Recurring ID:", + request.recurringPayment?.recurringPaymentUID ?? '-'), + _labelValueRow( + "Amount:", + _formatCurrencyAmount( + currencySymbol, request.recurringPayment?.amount)), + _labelValueRow("Variable Amount:", + (request.recurringPayment?.isVariable ?? false) ? "Yes" : "No"), ], // Description & Attachments _labelValueRow("Description:", request.description ?? '-'), - _labelValueRow("Attachment:", (request.attachments ?? []).isNotEmpty ? "Yes" : "No"), + _labelValueRow("Attachment:", + (request.attachments ?? []).isNotEmpty ? "Yes" : "No"), ], ); } diff --git a/lib/view/finance/payment_request_screen.dart b/lib/view/finance/payment_request_screen.dart index 0952184..f826785 100644 --- a/lib/view/finance/payment_request_screen.dart +++ b/lib/view/finance/payment_request_screen.dart @@ -355,7 +355,6 @@ class _PaymentRequestMainScreenState extends State child: InkWell( borderRadius: BorderRadius.circular(8), onTap: () { - // Navigate to detail screen, passing the payment request ID Get.to(() => PaymentRequestDetailScreen(paymentRequestId: item.id)); }, child: Padding( @@ -366,6 +365,30 @@ class _PaymentRequestMainScreenState extends State Row( children: [ MyText.bodyMedium(item.expenseCategory.name, fontWeight: 600), + + // ------------------------------- + // ADV CHIP (only if advance) + // ------------------------------- + if (item.isAdvancePayment == true) ...[ + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.orange.withOpacity(0.2), + borderRadius: BorderRadius.circular(4), + border: Border.all(color: Colors.orange), + ), + child: const Text( + "ADV", + style: TextStyle( + fontSize: 10, + color: Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + ), + ], ], ), const SizedBox(height: 6),