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/Insurers/insurer.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/search_field_theme.dart'; class InsurerList extends ConsumerStatefulWidget { const InsurerList({super.key}); @override ConsumerState createState() => InsurerListState(); } class InsurerListState extends ConsumerState { int currentPage = 1; int itemsPerPage = 10; late ApiService apiService; dynamic managerId; dynamic role; dynamic prefid; List> getInsurerData = []; List> filteredData = []; bool isLoading = false; Map? selectedInsurer; dynamic selectedId; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); apiService = ApiService(); Future.microtask(() { prefid = ref.read(managerIdProvider); role = ref.read(userRoleProvider); if (prefid != null && role != null) { getInsurers(); } }); } @override void dispose() { _searchController.dispose(); super.dispose(); } List get _paginatedData { final sortedData = [...filteredData] ..sort((a, b) { final idA = int.tryParse(a['id']?.toString() ?? '') ?? 0; final idB = int.tryParse(b['id']?.toString() ?? '') ?? 0; return idB.compareTo(idA); }); if (sortedData.isEmpty) return []; 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']; selectedInsurer = item; }); } void filterData(String query) { setState(() { final q = query.toLowerCase().trim(); if (q.isEmpty) { filteredData = List.from(getInsurerData); return; } filteredData = getInsurerData.where((item) { final name = (item['name'] ?? '').toString().toLowerCase(); final code = (item['short_name'] ?? '').toString().toLowerCase(); return name.contains(q) || code.contains(q); }).toList(); }); } Future getInsurers() async { setState(() => isLoading = true); try { final response = await apiService.fetchMasterDropDown('Insurers'); if (response['status'] == 200 || response['status'] == 'success') { setState(() { getInsurerData = List>.from(response['data']); filteredData = List.from(getInsurerData); }); } else { getInsurerData = []; filteredData = []; } } catch (_) { getInsurerData = []; filteredData = []; } finally { if (mounted) setState(() => isLoading = false); } } @override Widget build(BuildContext context) { managerId = ref.watch(managerIdProvider); return MainLayout( title: 'Insurer', body: SelectionArea( child: SizedBox( width: MediaQuery.of(context).size.width, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( onTap: () => context.go(AppRoutes.dashboard), child: Text( 'Insurer', style: GoogleFonts.poppins( fontSize: 14, fontWeight: FontWeight.w500, ), ), ), const SizedBox(height: 5), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Insurer( key: ValueKey(selectedId), data: selectedInsurer, id: selectedId, onSubmit: () { getInsurers(); setState(() { selectedInsurer = null; selectedId = null; }); }, ), const Spacer(), ThemedSearchField( hintText: 'Search', backgroundColor: const Color(0xFFFFFFFF), txtHeight: 30, onChanged: filterData, controller: _searchController, txtwidth: MediaQuery.of(context).size.width * 0.15, ), const SizedBox(width: 10), ExportBtn( sheetName: 'Insurer', fileName: 'insurer_list', txt: !ResponsiveLayout.isMobile(context), data: filteredData, displayHeaders: [ 'S.No.', 'Insurer', 'Short Name', ], keys: ['sno', 'name', 'short_name'], ), ], ), const SizedBox(height: 10), Container( decoration: BoxDecoration( color: const Color(0xFFF1F5F9), borderRadius: BorderRadius.circular(6), ), padding: const EdgeInsets.symmetric( vertical: 8, horizontal: 16, ), child: Row( children: [ SizedBox(width: 100, child: Text('S.No.', style: _headerStyle)), Expanded(flex: 2, child: Text('Insurer', style: _headerStyle)), Expanded(flex: 1, child: Text('Short Name', style: _headerStyle)), Expanded(flex: 1, child: Text('Action', style: _headerStyle)), ], ), ), Expanded( child: ColoredBox( color: Colors.white, child: _buildDataTable(), ), ), ], ), ), ), PaginationControls( currentPage: currentPage, itemsPerPage: itemsPerPage, totalItems: filteredData.length, onPageChanged: (page) => setState(() => currentPage = page), onItemsPerPageChanged: (items) { setState(() { itemsPerPage = items; currentPage = 1; }); }, ), ], ), ), ), ); } Widget _buildDataTable() { if (isLoading) { return const Center(child: CircularProgressIndicator()); } if (filteredData.isEmpty) { return const SizedBox( height: 50, child: Center(child: Text('No available data')), ); } final sortedData = [..._paginatedData]; return ListView.builder( itemCount: sortedData.length, itemBuilder: (context, index) { final startIndex = ((currentPage - 1) * itemsPerPage); final item = sortedData[index]; final sno = startIndex + index + 1; return _buildDataRow(item, sno); }, ); } Widget _buildDataRow(Map item, int sno) { return Container( padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 16), decoration: const BoxDecoration( color: Colors.white, border: Border( bottom: BorderSide(color: Colors.blueGrey, width: 0.15), ), ), child: Row( children: [ SizedBox(width: 100, child: Text('$sno', style: _dataBold)), Expanded( flex: 2, child: Text(item['name'] ?? '-', style: _dataBold), ), Expanded( flex: 1, child: Text(item['short_name'] ?? '-', style: _dataBold), ), Expanded( flex: 1, child: Tooltip( message: 'Edit', child: IconButton( icon: Image.asset( 'assets/miscellaneous/Edit.png', height: 12, width: 15, ), onPressed: () => handleEdit(item), splashRadius: 28, hoverColor: Colors.black12, padding: const EdgeInsets.all(8), constraints: const BoxConstraints(), ), ), ), ], ), ); } static final _dataBold = GoogleFonts.inter( fontSize: 11.5, fontWeight: FontWeight.w400, color: const Color(0xFF000000), ); static final _headerStyle = GoogleFonts.poppins( fontSize: 11.2, fontWeight: FontWeight.w500, color: const Color(0xFF1E293B), ); }