diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart index a95e8ee..95b02ff 100644 --- a/lib/core/services/api_service.dart +++ b/lib/core/services/api_service.dart @@ -2192,13 +2192,26 @@ class ApiService { return response; } - Future> getPayoutList() async { + Future> getPayoutList({ + String? fromDate, + String? toDate, + }) async { // print(_token); if (_token == null) { await _initializeToken(); } - final url = Uri.parse('${Env.apiUrl}invoice/list'); + final Uri url; + if (fromDate != null && + fromDate.isNotEmpty && + toDate != null && + toDate.isNotEmpty) { + url = Uri.parse('${Env.apiUrl}invoice/list').replace( + queryParameters: {'from_date': fromDate, 'to_date': toDate}, + ); + } else { + url = Uri.parse('${Env.apiUrl}invoice/list'); + } final headers = { 'Authorization': 'Bearer $_token' ?? '', diff --git a/lib/presentation/screens/payout/payout_list.dart b/lib/presentation/screens/payout/payout_list.dart index ef6baa5..5312f96 100644 --- a/lib/presentation/screens/payout/payout_list.dart +++ b/lib/presentation/screens/payout/payout_list.dart @@ -70,7 +70,12 @@ class _PayoutListState extends ConsumerState { }); try { - final response = await apiService.getPayoutList(); + final from = controllers['startDate']?.text.trim() ?? ''; + final to = controllers['endDate']?.text.trim() ?? ''; + final response = await apiService.getPayoutList( + fromDate: from.isNotEmpty ? from : null, + toDate: to.isNotEmpty ? to : null, + ); if (response['status'] == 'success') { print('PL 3 => getPayoutList - ${response['data']}'); @@ -78,7 +83,8 @@ class _PayoutListState extends ConsumerState { print(' PL 4 => getPayoutList => ${response['data']}'); setState(() { - + currentPage = 1; + if (data is List) { // Already a list of maps getPayoutData = List>.from(data); @@ -145,7 +151,9 @@ class _PayoutListState extends ConsumerState { return sortedData.sublist(startIndex, endIndex); } - void filterDateRange() {} + void filterDateRange() { + getPayoutList(); + } void refrshfilterDateRange() { setState(() { @@ -166,22 +174,17 @@ class _PayoutListState extends ConsumerState { final q = query.toLowerCase(); setState(() { filteredData = getPayoutData.where((item) { - // Search against the same display strings as the table (not raw API values). - final updatedAtSearch = _exportUpdatedAtForExcel(item['updated_at']) - .toLowerCase(); + // Search matches visible table columns only (broker / referer / updated hidden). final invoiceDateSearch = _formatDateSafe(item['invoice_date']) .toLowerCase(); final statusSearch = _exportPayoutStatusLabel(item['payout_status']).toLowerCase(); - return updatedAtSearch.contains(q) || - invoiceDateSearch.contains(q) || + return invoiceDateSearch.contains(q) || (item['invoice_no'] ?? '-').toLowerCase().contains(q) || (item['invoice_amount_indian_format'] ?? '-') .toLowerCase() .contains(q) || - (item['broker_name'] ?? '-').toLowerCase().contains(q) || - (item['partner_names'] ?? '-').toLowerCase().contains(q) || (item['utr_numbers'] ?? '-').toLowerCase().contains(q) || (item['invoiced_amount'] ?? '0').toLowerCase().contains(q) || (item['payout_amount'] ?? '0').toLowerCase().contains(q) || @@ -214,15 +217,6 @@ class _PayoutListState extends ConsumerState { } } - String _formatTime(String rawDate) { - try { - final dateTime = DateTime.parse(rawDate); - return DateFormat('HH:mm').format(dateTime); - } catch (e) { - return '-'; - } - } - /// Excel export: match table (1 = Pending, 2 = Completed). String _exportPayoutStatusLabel(dynamic v) { if (v == null) return '-'; @@ -233,19 +227,6 @@ class _PayoutListState extends ConsumerState { return 'Completed'; } - /// Excel export: same as table — dd-MM-yyyy + 24h time in one cell. - String _exportUpdatedAtForExcel(dynamic v) { - if (v == null) return '-'; - final raw = v.toString().trim(); - if (raw.isEmpty || raw.toLowerCase() == 'null') return '-'; - try { - final dateTime = DateTime.parse(raw); - return '${DateFormat('dd-MM-yyyy').format(dateTime)} ${DateFormat('HH:mm').format(dateTime)}'; - } catch (_) { - return raw; - } - } - String _displayText(dynamic value) { if (value == null) return '-'; final text = value.toString().trim(); @@ -258,18 +239,6 @@ class _PayoutListState extends ConsumerState { return '${value.substring(0, maxChars)}...'; } - String _partnerTooltipText(dynamic value) { - final text = _displayText(value); - if (text == '-') return text; - final items = text - .split(',') - .map((e) => e.trim()) - .where((e) => e.isNotEmpty) - .toList(); - if (items.isEmpty) return text; - return items.join('\n'); - } - String _utrTooltipText(dynamic value) { final text = _displayText(value); if (text == '-') return text; @@ -685,14 +654,36 @@ class _PayoutListState extends ConsumerState { ); } + Widget _payoutInvoiceDateFilter(BuildContext context) { + return DateFilterRow( + compactDateFiltersOnly: true, + dataFrom: 'Payout', + role: roleId, + id: userId, + selectedStaffId: null, + startController: controllers['startDate']!, + endController: controllers['endDate']!, + onStatusChanged: (_) {}, + formKey: _formKey, + isMobile: ResponsiveLayout.isMobile(context), + onFilter: filterDateRange, + onRefresh: refrshfilterDateRange, + ); + } + Widget _buildContent(BuildContext context) { return Column( children: [ + if (ResponsiveLayout.isMobile(context)) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: _payoutInvoiceDateFilter(context), + ), Container( // height: 40, // color: Colors.pink, child: Row( - crossAxisAlignment: CrossAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end, children: [ Text( @@ -702,8 +693,20 @@ class _PayoutListState extends ConsumerState { fontWeight: FontWeight.w400, ), ), - - Spacer(), + if (!ResponsiveLayout.isMobile(context)) ...[ + const SizedBox(width: 16), + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: _payoutInvoiceDateFilter(context), + ), + ), + ), + ] else ...[ + const Spacer(), + ], ThemedSearchField( hintText: 'Search', // backgroundColor: Color(0xFFF6F8F8), @@ -753,31 +756,24 @@ class _PayoutListState extends ConsumerState { "S.No", "Invoice No", "Invoice Date", - "Broker Name", - "Referer", - "UTR Details", + "UTR Number", "Invoiced Amount", "Payout Amount", "Balance Amount", "Status", - "Updated Date", ], keys: [ "id", "invoice_no", "invoice_date", - "broker_name", - "partner_names", "utr_numbers", "invoiced_amount", "payout_amount", "balance_amount", "payout_status", - "updated_at", ], valueFormatters: { 'payout_status': (v, _) => _exportPayoutStatusLabel(v), - 'updated_at': (v, _) => _exportUpdatedAtForExcel(v), }, ), ], @@ -801,29 +797,17 @@ class _PayoutListState extends ConsumerState { flex: 3, child: Text('Invoice No', style: _headerStyle), ), + Expanded(flex: 2, child: Text('UTR Number', style: _headerStyle)), + Expanded(flex: 2, child: Text('Invoiced Amount', style: _headerStyle),), Expanded( flex: 2, - child: Text('Broker Name', style: _headerStyle), - ), - Expanded(flex: 3, child: Text('Referer', style: _headerStyle)), - Expanded(flex: 2, child: Text('UTR Details', style: _headerStyle)), - Expanded( - flex: 2, - child: Text('Invoiced\nAmount', style: _headerStyle), + child: Text('Payout Amount', style: _headerStyle), ), Expanded( flex: 2, - child: Text('Payout\nAmount', style: _headerStyle), - ), - Expanded( - flex: 2, - child: Text('Balance\nAmount', style: _headerStyle), + child: Text('Balance Amount', style: _headerStyle), ), Expanded(flex: 2, child: Text('Status', style: _headerStyle)), - Expanded( - flex: 2, - child: Text('Updated Date', style: _headerStyle), - ), Expanded(flex: 2, child: Text('Action', style: _headerStyle)), ], ), @@ -897,29 +881,6 @@ class _PayoutListState extends ConsumerState { maxLines: 3, ), ), - Expanded( - flex: 2, - child: Text( - _displayText(item['broker_name']), - style: _dataBold, - softWrap: true, - maxLines: 3, - ), - ), - Expanded( - flex: 3, - child: Tooltip( - message: _partnerTooltipText(item['partner_names']), - waitDuration: const Duration(milliseconds: 250), - child: Text( - _truncateText(_displayText(item['partner_names']), maxChars: 25), - style: _dataBold, - softWrap: false, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - ), - ), Expanded( flex: 2, child: Tooltip( @@ -976,30 +937,6 @@ class _PayoutListState extends ConsumerState { ), ), - Expanded( - flex: 2, - child: item['updated_at'] != null - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - _formatDate(item['updated_at']), - style: _dataBold, - softWrap: false, - maxLines: 1, - ), - Text( - _formatTime(item['updated_at']), - style: _dataBold, - softWrap: false, - maxLines: 1, - ), - ], - ) - : Text('-', style: _dataBold), - ), - // ACTION ICONS (Edit + Delete) Expanded( flex: 2, diff --git a/lib/presentation/screens/payout/payout_report.dart b/lib/presentation/screens/payout/payout_report.dart index e145f03..8561892 100644 --- a/lib/presentation/screens/payout/payout_report.dart +++ b/lib/presentation/screens/payout/payout_report.dart @@ -61,6 +61,14 @@ class _PayoutReportScreenState extends ConsumerState { return v == 'no'; } + /// UI / export: capitalize first letter, lowercase the rest (e.g. `yes` → `Yes`). + String _receivedLabel(dynamic v) { + final s = v?.toString().trim() ?? ''; + if (s.isEmpty) return '-'; + return s[0].toUpperCase() + + (s.length > 1 ? s.substring(1).toLowerCase() : ''); + } + String? _agentIdForApi() { if (_isAgentRole()) { final uid = ref.read(userIdProvider); @@ -793,6 +801,9 @@ class _PayoutReportScreenState extends ConsumerState { 'utr_no', 'received_or_not', ], + valueFormatters: { + 'received_or_not': (v, _) => _receivedLabel(v), + }, ); if (mounted) { ToastHelper.showSuccessToast(context, 'Export finished'); @@ -974,7 +985,7 @@ class _PayoutReportScreenState extends ConsumerState { _buildSearchAndActions(context), ], ); - } + } Widget _tableHeader() { return Container( @@ -1103,7 +1114,7 @@ class _PayoutReportScreenState extends ConsumerState { Expanded( flex: 2, child: Text( - _cell(item, ['received_or_not']), + _receivedLabel(item['received_or_not']), style: rowStyle, maxLines: 2, overflow: TextOverflow.ellipsis, diff --git a/lib/presentation/widgets/custom_Stdate_EnDate_Filter.dart b/lib/presentation/widgets/custom_Stdate_EnDate_Filter.dart index ddc8f41..8fdfc3d 100644 --- a/lib/presentation/widgets/custom_Stdate_EnDate_Filter.dart +++ b/lib/presentation/widgets/custom_Stdate_EnDate_Filter.dart @@ -54,6 +54,9 @@ class DateFilterRow extends ConsumerStatefulWidget { final VoidCallback onRefresh; final GlobalKey formKey; final bool isMobile; + /// When true, only start/end date fields and filter/refresh actions are shown + /// (no status, staff, insurer, or partner controls). + final bool compactDateFiltersOnly; final role; final id; @@ -77,6 +80,7 @@ class DateFilterRow extends ConsumerStatefulWidget { required this.role, required this.id, this.isMobile = false, + this.compactDateFiltersOnly = false, this.dataFrom, }); @@ -116,6 +120,7 @@ class _DateFilterRowState extends ConsumerState { // final handlerId = ref.watch(handlerIdProvider); role = ref.watch(userRoleProvider); print("managerId - $managerId"); + if (widget.compactDateFiltersOnly) return; if (userID != null && role != null) { print('hansles'); getStaffDetails(userID); @@ -235,7 +240,8 @@ class _DateFilterRowState extends ConsumerState { @override Widget build(BuildContext context) { - if (widget.role == 'Accounts' && + if (!widget.compactDateFiltersOnly && + widget.role == 'Accounts' && widget.dataFrom == 'Policy' && filteredPartnerData.isEmpty && !_partnerFetchAttempted) { @@ -275,23 +281,24 @@ class _DateFilterRowState extends ConsumerState { buildEndDate(context), SizedBox(width: spacing), - if (widget.dataFrom == null && widget.dataFrom != 'Policy') ...[ - buildStatusSearch(context,widget.role), - SizedBox(width: spacing), - ], + if (!widget.compactDateFiltersOnly) ...[ + if (widget.dataFrom == null && widget.dataFrom != 'Policy') ...[ + buildStatusSearch(context, widget.role), + SizedBox(width: spacing), + ], - if (widget.role == 'manager' || widget.role == 'handler') ...[ - buildSelectStaffMem(context), - SizedBox(width: spacing), + if (widget.role == 'manager' || widget.role == 'handler') ...[ + buildSelectStaffMem(context), + SizedBox(width: spacing), + ], + if (widget.role == 'Accounts' && widget.dataFrom == 'Policy') ...[ + buildSelectPartnerAccountsPolicy(context), + SizedBox(width: spacing), + buildPolicyReportFlagSearch(context), + SizedBox(width: spacing), + buildSelectInsurer(context), + ], ], - if (widget.role == 'Accounts' && widget.dataFrom == 'Policy') ...[ - buildSelectPartnerAccountsPolicy(context), - SizedBox(width: spacing), - buildPolicyReportFlagSearch(context), - SizedBox(width: spacing), - buildSelectInsurer(context), - ], - ]; final buttons = [ diff --git a/pubspec.lock b/pubspec.lock index abbeba9..ea3eafc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" charcode: dependency: transitive description: @@ -780,26 +780,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -1297,10 +1297,10 @@ packages: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.10" toastification: dependency: "direct main" description: @@ -1502,5 +1502,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.8.1 <4.0.0" + dart: ">=3.9.0-0 <4.0.0" flutter: ">=3.32.0"