import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; import 'package:nhance_partner/presentation/screens/Masters/PaymentMode/payment.dart'; import '../../../../core/routing/routes.dart'; import '../../../../core/services/api_service.dart'; import '../../../../data/utils/Pagination.dart'; import '../../../layouts/main_layout.dart'; import '../../../layouts/responsive_layout.dart'; import '../../../providers/manager_provider.dart'; import '../../../themes/indicators/export_btn.dart'; import '../../../themes/indicators/filter_btn.dart'; import '../../../themes/indicators/search_field_theme.dart'; import '../../../themes/indicators/text_field_theme.dart'; import '../../../widgets/custom_action_popup.dart'; class PaymentLsit extends ConsumerStatefulWidget { const PaymentLsit({super.key}); @override ConsumerState createState() => PaymentLsitState(); } class PaymentLsitState extends ConsumerState { int currentPage = 1; int itemsPerPage = 10; late ApiService apiService; dynamic managerId; dynamic role; dynamic prefid; dynamic userId; // List> dataVal = []; List> getPaymentData = []; List> originalData = []; List> filteredData = []; bool isLoading = false; Map? selectedPayment; dynamic selectedId; @override void initState() { super.initState(); apiService = ApiService(); Future.microtask(() { final data1 = ref.read(managerIdProvider); // final data2 = ref.read(handlerIdProvider); print("Edata1 => mId: $data1 -2 :"); prefid = data1; role = ref.read(userRoleProvider); userId = ref.watch(userIdProvider); print("E43 => mId: $prefid"); if (prefid != null && role != null) { getPayment(); } }); // getPaymentList(); } List get _paginatedData { // Sort descending by id first final sortedData = [...filteredData] ..sort((a, b) => int.parse(b['id']) - int.parse(a['id'])); if (sortedData.isEmpty) return []; // Ensure currentPage is valid final maxPage = (sortedData.length / itemsPerPage).ceil(); final safePage = currentPage.clamp(1, maxPage); final startIndex = (safePage - 1) * itemsPerPage; final endIndex = (startIndex + itemsPerPage).clamp(0, sortedData.length); return sortedData.sublist(startIndex, endIndex); } void handleEdit(Map item) { setState(() { selectedId = item['id']; selectedPayment = item; }); } void filterData(String query) { setState(() { final q = query.toLowerCase(); if (q.isEmpty) { filteredData = getPaymentData; return; } filteredData = getPaymentData.where((item) { final isActiveStatus = item['is_active'] == "1" ? "active" : "inactive"; return (item['value'] ?? '').toString().toLowerCase().contains(q) || isActiveStatus.contains(q); }).toList(); }); } final TextEditingController _searchStaffController = TextEditingController(); Future getPayment() async { print('getPayment called'); setState(() { isLoading = true; }); try { final response = await apiService.fetchMasterDropDown('PaymentMode'); if (response['status'] == 200) { print('getPayment - ${response['data']}'); setState(() { getPaymentData = List>.from(response['data']); print('API Data - $getPaymentData'); filteredData = List.from(getPaymentData); print('originalData - $filteredData'); }); } else { getPaymentData = []; filteredData = []; } } catch (e) { print('Exception occurred: $e'); } finally { setState(() { isLoading = false; }); } } List _buildPopupMenuActions(BuildContext context, dynamic data) { return [ GestureDetector( onTap: () { Navigator.pop(context); print('EDITStaff - ${data['id']}'); dynamic id = data['id']; context.go('/staff/$id'); }, child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.edit_sharp, color: Color(0xFF319718), size: 18), SizedBox(width: 10), Text('Edit'), ], ), ), ]; } @override Widget build(BuildContext context) { managerId = ref.watch(managerIdProvider); return MainLayout( title: "Staff", body: SelectionArea( child: Container( // padding: EdgeInsets.all(8.0), // margin: EdgeInsets.all(10.0), // color: Colors.yellow.shade50, width: MediaQuery.of(context).size.width, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ // Container( // // height: 30, // // color: Colors.red.shade50, // width: MediaQuery.of(context).size.width, // child: GestureDetector( // onTap: () { // context.go(AppRoutes.dashboard); // }, // child: Row( // crossAxisAlignment: CrossAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.start, // children: [ // Text( // 'Payment List', // style: GoogleFonts.poppins( // fontSize: 14, // fontWeight: FontWeight.w500, // ), // ), // ], // ), // ), // ), Text( 'Payment', style: GoogleFonts.poppins( fontSize: 14, fontWeight: FontWeight.w500, ), ), SizedBox(height: 5), Expanded( child: Container( // color: Colors.green, // color: Colors.green.shade50, width: MediaQuery.of(context).size.width, // margin: EdgeInsets.all(10.0), decoration: BoxDecoration( // color: Colors.white, borderRadius: BorderRadius.circular(15.0), ), padding: EdgeInsets.all(8.0), child: Column( children: [ Container( // height: 40, // color: Colors.pink, child: Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.start, children: [ Payment( key: ValueKey(selectedId), data: selectedPayment, id: selectedId, onSubmit: () { getPayment(); setState(() { selectedPayment = null; selectedId = null; }); // reset after save }, ), Spacer(), ThemedSearchField( hintText: 'Search', // backgroundColor: Color(0xFFF6F8F8), backgroundColor: Color(0xFFFFFFFF), txtHeight: 30, onChanged: filterData, controller: _searchStaffController, txtwidth: MediaQuery.of(context).size.width * 0.15, ), SizedBox(width: 10), ExportBtn( sheetName: "Payment", fileName: "Payment_list", txt: !ResponsiveLayout.isMobile(context) ? true : false, data: filteredData, displayHeaders: ['S.No.', 'Payment', 'Status'], keys: ["sno", "value", "is_active"], ), ], ), ), SizedBox(height: 10), Container( decoration: BoxDecoration( color: Color(0xFFF1F5F9), // color: Color(0xFFEDF6F5), borderRadius: BorderRadius.circular(6), ), padding: const EdgeInsets.symmetric( vertical: 10, horizontal: 16, ), child: Row( children: [ // Expanded( // flex: 1, // child: Text('S.No.', style: _headerStyle), // ), SizedBox( width: 50, child: Text('S.No.', style: _headerStyle), ), Expanded( flex: 1, child: Text('Payment', style: _headerStyle), ), Expanded( flex: 1, child: Text('Status', style: _headerStyle), ), Expanded( flex: 1, child: Text('Action', style: _headerStyle), ), Expanded( flex: 1, child: Text('', style: _headerStyle), ), Expanded( flex: 1, child: Text('', style: _headerStyle), ), ], ), ), Expanded( child: Container( color: Colors.white, child: _buildDataTable(context), ), ), ], ), ), ), Container( // height: 20, width: MediaQuery.of(context).size.width, // color: Colors.green.shade50, child: PaginationControls( currentPage: currentPage, itemsPerPage: itemsPerPage, // totalItems: dataVal.length, totalItems: filteredData.length, // activeColor: layoutColor, // your theme color onPageChanged: (page) { setState(() { currentPage = page; }); }, onItemsPerPageChanged: (items) { setState(() { itemsPerPage = items; currentPage = 1; }); }, ), ), ], ), ) ), ); } Widget _buildDataTable(BuildContext context) { if (filteredData.isEmpty) { return const SizedBox( height: 50, child: Center(child: Text('No available data')), ); } final sortedData = [..._paginatedData]; return ListView.builder( // itemCount: filteredData.length + 1, // +1 for header, +1 for pagination itemCount: sortedData.length + 1, // +1 for header, +1 for pagination itemBuilder: (context, index) { if (index == 0) return _buildHeader(); // if (index == dataVal.length + 1) // return _buildPagination(context); final startIndex = ((currentPage - 1) * itemsPerPage); // final item = filteredData[index - 1]; final item = sortedData[index - 1]; final sno = startIndex + index; return _buildDataRow(item, sno); }, ); } Widget _buildHeader() { return SizedBox.shrink(); } Widget _buildDataRow(Map item, sno) { return Container( padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16), // margin: const EdgeInsets.only(top: 10), decoration: BoxDecoration( color: Colors.white, // color: Color(0xFFE0F7F9), border: const Border( bottom: BorderSide(color: Colors.blueGrey, width: 0.15), ), // borderRadius: BorderRadius.circular(8), ), child: Row( children: [ SizedBox(width: 50, child: Text('$sno' ?? '-', style: _dataBold)), // Expanded(flex: 1, child: Text('$sno' ?? '-', style: _dataBold)), Expanded( flex: 1, child: Text(item['value'] ?? '-', style: _dataBold), ), Expanded( flex: 1, child: Row( children: [ Container( // color: Colors.yellow.shade50, child: Transform.scale( scale: 0.4, // reduce size (0.7–0.9 works well) child: Switch( value: item['is_active'] == "1", onChanged: (val) { setState(() { item['is_active'] = val ? "1" : "0"; }); final response = apiService.updateStatusMasters( item['id'], val ? "0" : "1", 'PaymentMode', userId, ); print("Response - $response"); }, activeColor: Color(0xFF2E7D6E), // thumb when active // activeColor: Color(0xFF425B5B), // thumb when active activeTrackColor: Color(0xFFDCFCE7), // track when active // activeTrackColor: Color(0xFFB2D8D3), // track when active inactiveThumbColor: Colors.grey.shade400, // thumb when inactive inactiveTrackColor: Colors.grey.shade300, // track when inactive ), ), ), ], ), ), Expanded( flex: 1, child: item['is_active'] == "1" ? Row( children: [ Tooltip( message: 'Edit', child: IconButton( icon: Image.asset( "assets/miscellaneous/Edit.png", height: 12, width: 15, ), onPressed: () { print('EDITBrokwer - ${item['id']}'); print('EDITBrokwer - ${item}'); dynamic id = item['id']; handleEdit(item); print(item); }, splashRadius: 28, hoverColor: Colors.black12, padding: const EdgeInsets.all(8), constraints: const BoxConstraints(), ), ), ], ) : Row( children: [ Image.asset( "assets/miscellaneous/Edit_muted.png", height: 15, width: 15, ), ], ), ), Expanded(flex: 1, child: Text('', style: _dataBold)), Expanded(flex: 1, child: Text('', style: _dataBold)), ], ), ); } static final _dataBold = GoogleFonts.inter( fontSize: 11.5, fontWeight: FontWeight.w400, color: Color(0xFF000000), ); static final _dataSub = GoogleFonts.inter( fontSize: 10, fontWeight: FontWeight.w300, color: Color(0xFF585757), ); static final _headerStyle = GoogleFonts.poppins( fontSize: 11.2, fontWeight: FontWeight.w500, color: Color(0xFF1E293B), ); }