nhance_partner/lib/presentation/screens/Masters/Insurers/insurerList.dart

323 lines
10 KiB
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/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<InsurerList> createState() => InsurerListState();
}
class InsurerListState extends ConsumerState<InsurerList> {
int currentPage = 1;
int itemsPerPage = 10;
late ApiService apiService;
dynamic managerId;
dynamic role;
dynamic prefid;
List<Map<String, dynamic>> getInsurerData = [];
List<Map<String, dynamic>> filteredData = [];
bool isLoading = false;
Map<String, dynamic>? 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<dynamic> 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<String, dynamic> 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<void> getInsurers() async {
setState(() => isLoading = true);
try {
final response = await apiService.fetchMasterDropDown('Insurers');
if (response['status'] == 200 || response['status'] == 'success') {
setState(() {
getInsurerData = List<Map<String, dynamic>>.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<String, dynamic> 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),
);
}