From 5db53c29dfcbb7695356b41f97e14b5196c07a1b Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Wed, 12 Nov 2025 11:23:13 +0530 Subject: [PATCH] added validation for payment request in and expense reumbersemrnt bottomsheet --- .../expense/expense_detail_controller.dart | 11 +- lib/helpers/services/api_service.dart | 30 +- .../expense/reimbursement_bottom_sheet.dart | 315 ++++++++++++++---- ...ent_request_rembursement_bottom_sheet.dart | 50 ++- lib/view/expense/expense_detail_screen.dart | 170 +++++----- 5 files changed, 392 insertions(+), 184 deletions(-) diff --git a/lib/controller/expense/expense_detail_controller.dart b/lib/controller/expense/expense_detail_controller.dart index fde0d86..afc925a 100644 --- a/lib/controller/expense/expense_detail_controller.dart +++ b/lib/controller/expense/expense_detail_controller.dart @@ -142,6 +142,10 @@ class ExpenseDetailController extends GetxController { required String reimburseDate, required String reimburseById, required String statusId, + double? baseAmount, + double? taxAmount, + double? tdsPercent, + double? netPayable, }) async { final success = await _apiCallWrapper( () => ApiService.updateExpenseStatusApi( @@ -151,13 +155,16 @@ class ExpenseDetailController extends GetxController { reimburseTransactionId: reimburseTransactionId, reimburseDate: reimburseDate, reimbursedById: reimburseById, + baseAmount: baseAmount, + taxAmount: taxAmount, + tdsPercent: tdsPercent, + netPayable: netPayable, ), "submit reimbursement", ); if (success == true) { - // Explicitly check for true as _apiCallWrapper returns T? - await fetchExpenseDetails(); // Refresh details after successful update + await fetchExpenseDetails(); return true; } else { errorMessage.value = "Failed to submit reimbursement."; diff --git a/lib/helpers/services/api_service.dart b/lib/helpers/services/api_service.dart index 88c1687..d0d942d 100644 --- a/lib/helpers/services/api_service.dart +++ b/lib/helpers/services/api_service.dart @@ -1705,34 +1705,32 @@ class ApiService { String? reimburseTransactionId, String? reimburseDate, String? reimbursedById, + double? baseAmount, + double? taxAmount, + double? tdsPercent, + double? netPayable, }) async { final Map payload = { "expenseId": expenseId, "statusId": statusId, }; - if (comment != null) { - payload["comment"] = comment; - } - if (reimburseTransactionId != null) { + if (comment != null) payload["comment"] = comment; + if (reimburseTransactionId != null) payload["reimburseTransactionId"] = reimburseTransactionId; - } - if (reimburseDate != null) { - payload["reimburseDate"] = reimburseDate; - } - if (reimbursedById != null) { - payload["reimburseById"] = reimbursedById; - } + if (reimburseDate != null) payload["reimburseDate"] = reimburseDate; + if (reimbursedById != null) payload["reimburseById"] = reimbursedById; + if (baseAmount != null) payload["baseAmount"] = baseAmount; + if (taxAmount != null) payload["taxAmount"] = taxAmount; + if (tdsPercent != null) payload["tdsPercent"] = tdsPercent; + if (netPayable != null) payload["netPayable"] = netPayable; const endpoint = ApiEndpoints.updateExpenseStatus; logSafe("Updating expense status with payload: $payload"); try { - final response = await _postRequest( - endpoint, - payload, - customTimeout: extendedTimeout, - ); + final response = + await _postRequest(endpoint, payload, customTimeout: extendedTimeout); if (response == null) { logSafe("Update expense status failed: null response", diff --git a/lib/model/expense/reimbursement_bottom_sheet.dart b/lib/model/expense/reimbursement_bottom_sheet.dart index c996174..c2d235c 100644 --- a/lib/model/expense/reimbursement_bottom_sheet.dart +++ b/lib/model/expense/reimbursement_bottom_sheet.dart @@ -20,6 +20,10 @@ class ReimbursementBottomSheet extends StatefulWidget { required String reimburseDate, required String reimburseById, required String statusId, + required double baseAmount, + required double taxAmount, + required double tdsPercent, + required double netPayable, }) onSubmit; const ReimbursementBottomSheet({ @@ -41,15 +45,44 @@ class _ReimbursementBottomSheetState extends State { final TextEditingController commentCtrl = TextEditingController(); final TextEditingController txnCtrl = TextEditingController(); + final TextEditingController baseAmountCtrl = TextEditingController(); + final TextEditingController gstAmountCtrl = TextEditingController(); + final TextEditingController tdsCtrl = TextEditingController(text: '0'); + final RxString dateStr = ''.obs; + final RxDouble tdsAmount = 0.0.obs; + final RxDouble netPayable = 0.0.obs; + + @override + void initState() { + super.initState(); + baseAmountCtrl.addListener(_recalculate); + gstAmountCtrl.addListener(_recalculate); + tdsCtrl.addListener(_recalculate); + } @override void dispose() { commentCtrl.dispose(); txnCtrl.dispose(); + baseAmountCtrl.dispose(); + gstAmountCtrl.dispose(); + tdsCtrl.dispose(); super.dispose(); } + void _recalculate() { + final double base = double.tryParse(baseAmountCtrl.text.trim()) ?? 0.0; + final double gst = double.tryParse(gstAmountCtrl.text.trim()) ?? 0.0; + final double tdsPercent = double.tryParse(tdsCtrl.text.trim()) ?? 0.0; + + final double calculatedTds = (base * tdsPercent) / 100; + final double net = (base + gst) - calculatedTds; + + tdsAmount.value = double.parse(calculatedTds.toStringAsFixed(2)); + netPayable.value = double.parse(net.toStringAsFixed(2)); + } + void _showEmployeeList() async { await showModalBottomSheet( context: context, @@ -67,7 +100,6 @@ class _ReimbursementBottomSheetState extends State { ), ); - // Optional cleanup controller.employeeSearchController.clear(); controller.employeeSearchResults.clear(); } @@ -94,6 +126,29 @@ class _ReimbursementBottomSheetState extends State { ); } + Widget _readOnlyValueBox(String label, String value, Color color) { + return Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 16), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + border: Border.all(color: color.withOpacity(0.3)), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + MyText.labelMedium(label), + MyText.bodyMedium( + "₹$value", + color: color, + fontWeight: 700, + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { return Obx(() { @@ -105,31 +160,73 @@ class _ReimbursementBottomSheetState extends State { Navigator.pop(context); }, onSubmit: () async { + final expenseTransactionDateStr = + controller.expense.value?.transactionDate; + DateTime? expenseTransactionDate; + if (expenseTransactionDateStr != null) { + try { + expenseTransactionDate = + DateTime.parse(expenseTransactionDateStr); + } catch (_) {} + } + if (commentCtrl.text.trim().isEmpty || - txnCtrl.text.trim().isEmpty || dateStr.value.isEmpty || - controller.selectedReimbursedBy.value == null) { + controller.selectedReimbursedBy.value == null || + baseAmountCtrl.text.trim().isEmpty || + gstAmountCtrl.text.trim().isEmpty) { showAppSnackbar( title: "Incomplete", - message: "Please fill all fields", + message: "Please fill all required fields", type: SnackbarType.warning, ); return; } + // Validate reimbursement date + final DateTime? selectedDate = DateTime.tryParse(dateStr.value); + if (selectedDate != null) { + final now = DateTime.now(); + + if (selectedDate.isAfter(now)) { + showAppSnackbar( + title: "Invalid Date", + message: "Reimbursement date cannot be in the future.", + type: SnackbarType.warning, + ); + return; + } + + if (expenseTransactionDate != null && + selectedDate.isBefore(expenseTransactionDate)) { + showAppSnackbar( + title: "Invalid Date", + message: + "Reimbursement date cannot be before the transaction date (${DateFormat('yyyy-MM-dd').format(expenseTransactionDate)}).", + type: SnackbarType.warning, + ); + return; + } + } + final success = await widget.onSubmit( comment: commentCtrl.text.trim(), - reimburseTransactionId: txnCtrl.text.trim(), + reimburseTransactionId: txnCtrl.text + .trim(), reimburseDate: dateStr.value, reimburseById: controller.selectedReimbursedBy.value!.id, statusId: widget.statusId, + baseAmount: double.tryParse(baseAmountCtrl.text.trim()) ?? 0, + taxAmount: double.tryParse(gstAmountCtrl.text.trim()) ?? 0, + tdsPercent: double.tryParse(tdsCtrl.text.trim()) ?? 0, + netPayable: netPayable.value, ); if (success) { Get.back(); showAppSnackbar( title: "Success", - message: "Reimbursement submitted", + message: "Reimbursement submitted successfully", type: SnackbarType.success, ); } else { @@ -140,76 +237,152 @@ class _ReimbursementBottomSheetState extends State { ); } }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - MyText.labelMedium("Comment"), - MySpacing.height(8), - TextField( - controller: commentCtrl, - decoration: _inputDecoration("Enter comment"), - ), - MySpacing.height(16), - MyText.labelMedium("Transaction ID"), - MySpacing.height(8), - TextField( - controller: txnCtrl, - decoration: _inputDecoration("Enter transaction ID"), - ), - MySpacing.height(16), - MyText.labelMedium("Reimbursement Date"), - MySpacing.height(8), - GestureDetector( - onTap: () async { - final picked = await showDatePicker( - context: context, - initialDate: dateStr.value.isEmpty - ? DateTime.now() - : DateFormat('yyyy-MM-dd').parse(dateStr.value), - firstDate: DateTime(2020), - lastDate: DateTime(2100), - ); - if (picked != null) { - dateStr.value = DateFormat('yyyy-MM-dd').format(picked); - } - }, - child: AbsorbPointer( - child: TextField( - controller: TextEditingController(text: dateStr.value), - decoration: _inputDecoration("Select Date").copyWith( - suffixIcon: const Icon(Icons.calendar_today), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MyText.labelMedium("Transaction ID*"), + MySpacing.height(8), + TextField( + controller: txnCtrl, + decoration: _inputDecoration("Enter transaction ID"), + ), + MySpacing.height(16), + MyText.labelMedium("Reimbursement Date*"), + MySpacing.height(8), + GestureDetector( + onTap: () async { + // Get transaction date from expense + DateTime? transactionDate; + if (controller.expense.value?.transactionDate != null) { + try { + transactionDate = DateTime.parse( + controller.expense.value!.transactionDate); + } catch (_) { + transactionDate = null; + } + } + + final DateTime now = DateTime.now(); + final DateTime firstDate = + transactionDate ?? DateTime(2020); // fallback if null + final DateTime lastDate = now; + + final picked = await showDatePicker( + context: context, + initialDate: now.isBefore(firstDate) + ? firstDate + : now, // initial date inside the range + firstDate: firstDate, + lastDate: lastDate, + ); + + if (picked != null) { + dateStr.value = DateFormat('yyyy-MM-dd').format(picked); + } + }, + child: AbsorbPointer( + child: TextField( + controller: TextEditingController(text: dateStr.value), + decoration: _inputDecoration("Select Date").copyWith( + suffixIcon: const Icon(Icons.calendar_today), + ), ), ), ), - ), - MySpacing.height(16), - MyText.labelMedium("Reimbursed By"), - MySpacing.height(8), - GestureDetector( - onTap: _showEmployeeList, - child: Container( - padding: - const EdgeInsets.symmetric(horizontal: 16, vertical: 14), - decoration: BoxDecoration( - color: Colors.grey.shade100, - borderRadius: BorderRadius.circular(12), - border: Border.all(color: Colors.grey.shade300), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - controller.selectedReimbursedBy.value == null - ? "Select Paid By" - : '${controller.selectedReimbursedBy.value?.firstName ?? ''} ${controller.selectedReimbursedBy.value?.lastName ?? ''}', - style: const TextStyle(fontSize: 14), - ), - const Icon(Icons.arrow_drop_down, size: 22), - ], + MySpacing.height(16), + MyText.labelMedium("Reimbursed By*"), + MySpacing.height(8), + GestureDetector( + onTap: _showEmployeeList, + child: Container( + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + decoration: BoxDecoration( + color: Colors.grey.shade100, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade300), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + controller.selectedReimbursedBy.value == null + ? "Select Paid By" + : '${controller.selectedReimbursedBy.value?.firstName ?? ''} ${controller.selectedReimbursedBy.value?.lastName ?? ''}', + style: const TextStyle(fontSize: 14), + ), + const Icon(Icons.arrow_drop_down, size: 22), + ], + ), ), ), - ), - ], + MySpacing.height(16), + MyText.labelMedium("Base Amount*"), + MySpacing.height(8), + TextField( + controller: baseAmountCtrl, + keyboardType: TextInputType.number, + decoration: _inputDecoration("Enter Base Amount"), + ), + MySpacing.height(16), + MyText.labelMedium("GST Amount*"), + MySpacing.height(8), + TextField( + controller: gstAmountCtrl, + keyboardType: TextInputType.number, + decoration: _inputDecoration("Enter GST Amount"), + ), + MySpacing.height(16), + MyText.labelMedium("TDS Percent"), + MySpacing.height(8), + TextField( + controller: tdsCtrl, + keyboardType: TextInputType.number, + decoration: _inputDecoration("Enter TDS Percent").copyWith( + suffixIcon: Padding( + padding: const EdgeInsets.only(right: 12), + child: Icon(Icons.percent, + size: 20, color: Colors.grey.shade600), + ), + suffixIconConstraints: + const BoxConstraints(minWidth: 0, minHeight: 0), + ), + onChanged: (_) => _recalculate(), + ), + MySpacing.height(4), + MyText.bodySmall( + "TDS is applied on base amount only.", + color: Colors.grey.shade600, + ), + MySpacing.height(16), + Obx(() => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _readOnlyValueBox( + "TDS Amount", + tdsAmount.value.toStringAsFixed(2), + Colors.orange, + ), + MySpacing.height(12), + _readOnlyValueBox( + "Net Payable", + netPayable.value.toStringAsFixed(2), + Colors.green, + ), + ], + )), + MySpacing.height(16), + MyText.labelMedium("Comment*"), + MySpacing.height(8), + TextField( + controller: commentCtrl, + maxLines: 2, + decoration: _inputDecoration("Enter comment"), + ), + MySpacing.height(16), + ], + ), ), ); }); diff --git a/lib/model/finance/payment_request_rembursement_bottom_sheet.dart b/lib/model/finance/payment_request_rembursement_bottom_sheet.dart index d4d273e..0c39ca6 100644 --- a/lib/model/finance/payment_request_rembursement_bottom_sheet.dart +++ b/lib/model/finance/payment_request_rembursement_bottom_sheet.dart @@ -117,6 +117,21 @@ class _UpdatePaymentRequestWithReimbursementState ); } + Widget _requiredLabel(String label) { + return RichText( + text: TextSpan( + text: label, + style: MyTextStyle.labelMedium(), + children: const [ + TextSpan( + text: ' *', + style: TextStyle(color: Colors.red), + ), + ], + ), + ); + } + Widget _readOnlyValueBox(String label, String value, Color color) { return Container( width: double.infinity, @@ -151,11 +166,11 @@ class _UpdatePaymentRequestWithReimbursementState Navigator.pop(context); }, onSubmit: () async { - if (commentCtrl.text.trim().isEmpty || - txnCtrl.text.trim().isEmpty || + if (txnCtrl.text.trim().isEmpty || dateStr.value.isEmpty || baseAmountCtrl.text.trim().isEmpty || - taxAmountCtrl.text.trim().isEmpty) { + taxAmountCtrl.text.trim().isEmpty || + commentCtrl.text.trim().isEmpty) { showAppSnackbar( title: "Incomplete", message: "Please fill all mandatory fields", @@ -199,8 +214,7 @@ class _UpdatePaymentRequestWithReimbursementState Get.close(1); } } - } catch (e, st) { - print("Error updating payment: $e\n$st"); + } catch (e) { showAppSnackbar( title: 'Error', message: 'Something went wrong. Please try again.', @@ -212,7 +226,7 @@ class _UpdatePaymentRequestWithReimbursementState child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - MyText.labelMedium("Transaction ID*"), + _requiredLabel("Transaction ID"), MySpacing.height(8), TextField( controller: txnCtrl, @@ -220,16 +234,24 @@ class _UpdatePaymentRequestWithReimbursementState ), MySpacing.height(16), - MyText.labelMedium("Transaction Date*"), + _requiredLabel("Transaction Date"), MySpacing.height(8), GestureDetector( onTap: () async { + final DateTime submittedDate = + controller.paymentRequest.value?.createdAt ?? + DateTime.now(); + final DateTime today = DateTime.now(); + final picked = await showDatePicker( context: context, - initialDate: DateTime.now(), - firstDate: DateTime(2020), - lastDate: DateTime.now(), + initialDate: + today.isBefore(submittedDate) ? submittedDate : today, + firstDate: submittedDate, + lastDate: today, + helpText: 'Select Transaction Date', ); + if (picked != null) { dateStr.value = DateFormat('dd-MM-yyyy').format(picked); } @@ -273,7 +295,7 @@ class _UpdatePaymentRequestWithReimbursementState ), MySpacing.height(16), - MyText.labelMedium("Base Amount"), + _requiredLabel("Base Amount"), MySpacing.height(8), TextField( controller: baseAmountCtrl, @@ -282,7 +304,7 @@ class _UpdatePaymentRequestWithReimbursementState ), MySpacing.height(16), - MyText.labelMedium("GST Amount"), + _requiredLabel("GST Amount"), MySpacing.height(8), TextField( controller: taxAmountCtrl, @@ -307,7 +329,6 @@ class _UpdatePaymentRequestWithReimbursementState ), onChanged: (_) => _recalculateTds(), ), - MySpacing.height(4), MyText.bodySmall( "TDS is applied on base amount only.", @@ -315,7 +336,6 @@ class _UpdatePaymentRequestWithReimbursementState ), MySpacing.height(16), - // ✅ Proper display section for TDS and Net Payable Obx(() => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -334,7 +354,7 @@ class _UpdatePaymentRequestWithReimbursementState )), MySpacing.height(20), - MyText.labelMedium("Comment*"), + _requiredLabel("Comment"), MySpacing.height(8), TextField( controller: commentCtrl, diff --git a/lib/view/expense/expense_detail_screen.dart b/lib/view/expense/expense_detail_screen.dart index 0e54853..b9109c1 100644 --- a/lib/view/expense/expense_detail_screen.dart +++ b/lib/view/expense/expense_detail_screen.dart @@ -31,10 +31,11 @@ class ExpenseDetailScreen extends StatefulWidget { State createState() => _ExpenseDetailScreenState(); } -class _ExpenseDetailScreenState extends State with UIMixin { +class _ExpenseDetailScreenState extends State + with UIMixin { final controller = Get.put(ExpenseDetailController()); final projectController = Get.find(); -final permissionController = Get.put(PermissionController()); + final permissionController = Get.put(PermissionController()); EmployeeInfo? employeeInfo; final RxBool canSubmit = false.obs; @@ -198,8 +199,8 @@ final permissionController = Get.put(PermissionController()); }, backgroundColor: contentTheme.primary, icon: const Icon(Icons.edit), - label: MyText.bodyMedium( - "Edit Expense", fontWeight: 600, color: Colors.white), + label: MyText.bodyMedium("Edit Expense", + fontWeight: 600, color: Colors.white), ); }), bottomNavigationBar: Obx(() { @@ -278,87 +279,96 @@ final permissionController = Get.put(PermissionController()); const reimbursementId = 'f18c5cfd-7815-4341-8da2-2c2d65778e27'; if (expense.status.id == reimbursementId) { showModalBottomSheet( - context: context, - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(5))), - builder: (context) => ReimbursementBottomSheet( - expenseId: expense.id, - statusId: next.id, - onClose: () {}, - onSubmit: ({ - required String comment, - required String reimburseTransactionId, - required String reimburseDate, - required String reimburseById, - required String statusId, - }) async { - final transactionDate = DateTime.tryParse( - controller.expense.value?.transactionDate ?? ''); - final selectedReimburseDate = - DateTime.tryParse(reimburseDate); - final today = DateTime.now(); + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(5))), + builder: (context) => ReimbursementBottomSheet( + expenseId: expense.id, + statusId: next.id, + onClose: () {}, + onSubmit: ({ + required String comment, + required String reimburseTransactionId, + required String reimburseDate, + required String reimburseById, + required String statusId, + required double baseAmount, + required double taxAmount, + required double tdsPercent, + required double netPayable, + }) async { + final transactionDate = DateTime.tryParse( + controller.expense.value?.transactionDate ?? ''); + final selectedReimburseDate = + DateTime.tryParse(reimburseDate); + final today = DateTime.now(); - if (transactionDate == null || - selectedReimburseDate == null) { - showAppSnackbar( - title: 'Invalid date', - message: - 'Could not parse transaction or reimbursement date.', - type: SnackbarType.error, - ); - return false; - } + if (transactionDate == null || + selectedReimburseDate == null) { + showAppSnackbar( + title: 'Invalid Date', + message: + 'Could not parse transaction or reimbursement date.', + type: SnackbarType.error, + ); + return false; + } - if (onlyDate(selectedReimburseDate) - .isBefore(onlyDate(transactionDate))) { - showAppSnackbar( - title: 'Invalid Date', - message: - 'Reimbursement date cannot be before the transaction date.', - type: SnackbarType.error, - ); - return false; - } + if (onlyDate(selectedReimburseDate) + .isBefore(onlyDate(transactionDate))) { + showAppSnackbar( + title: 'Invalid Date', + message: + 'Reimbursement date cannot be before the transaction date.', + type: SnackbarType.error, + ); + return false; + } - if (onlyDate(selectedReimburseDate) - .isAfter(onlyDate(today))) { - showAppSnackbar( - title: 'Invalid Date', - message: 'Reimbursement date cannot be in the future.', - type: SnackbarType.error, - ); - return false; - } + if (onlyDate(selectedReimburseDate) + .isAfter(onlyDate(today))) { + showAppSnackbar( + title: 'Invalid Date', + message: + 'Reimbursement date cannot be in the future.', + type: SnackbarType.error, + ); + return false; + } - final success = - await controller.updateExpenseStatusWithReimbursement( - comment: comment, - reimburseTransactionId: reimburseTransactionId, - reimburseDate: reimburseDate, - reimburseById: reimburseById, - statusId: statusId, - ); + final success = + await controller.updateExpenseStatusWithReimbursement( + comment: comment, + reimburseTransactionId: reimburseTransactionId, + reimburseDate: reimburseDate, + reimburseById: reimburseById, + statusId: statusId, + baseAmount: baseAmount, + taxAmount: taxAmount, + tdsPercent: tdsPercent, + netPayable: netPayable, + ); - if (success) { - Navigator.of(context).pop(); - showAppSnackbar( - title: 'Success', - message: 'Expense reimbursed successfully.', - type: SnackbarType.success, - ); - await controller.fetchExpenseDetails(); - return true; - } else { - showAppSnackbar( - title: 'Error', - message: 'Failed to reimburse expense.', - type: SnackbarType.error, - ); - return false; - } - }), - ); + if (success) { + Navigator.of(context).pop(); + showAppSnackbar( + title: 'Success', + message: 'Expense reimbursed successfully.', + type: SnackbarType.success, + ); + await controller.fetchExpenseDetails(); + return true; + } else { + showAppSnackbar( + title: 'Error', + message: 'Failed to reimburse expense.', + type: SnackbarType.error, + ); + return false; + } + }, + )); } else { final comment = await showCommentBottomSheet(context, next.name); if (comment == null) return;