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/core/routing/routes.dart'; import 'package:nhance_partner/core/services/api_service.dart'; import 'package:nhance_partner/data/utils/Pagination.dart'; import 'package:nhance_partner/presentation/layouts/main_layout.dart'; import 'package:nhance_partner/presentation/providers/userRoleProvider.dart'; import 'gridUpload.dart'; import 'package:nhance_partner/presentation/themes/indicators/search_field_theme.dart'; class GridListScreen extends ConsumerStatefulWidget { const GridListScreen({super.key}); @override ConsumerState createState() => _GridListScreenState(); } class _GridListScreenState extends ConsumerState { final ApiService _apiService = ApiService(); final TextEditingController _searchController = TextEditingController(); int _currentPage = 1; int _itemsPerPage = 10; bool _isLoading = false; List> _allRows = []; List> _filteredRows = []; bool get _showUploadButton { final role = (ref.watch(userRoleProvider) ?? '').toString().trim().toLowerCase(); return role == 'manager' || role == 'accounts'; } @override void initState() { super.initState(); Future.microtask(_loadGridList); } @override void dispose() { _searchController.dispose(); super.dispose(); } Future _loadGridList() async { setState(() => _isLoading = true); try { final response = await _apiService.fetchGridFileList(); if ((response['status'] ?? '').toString().toLowerCase() == 'success') { final rows = List>.from(response['data'] ?? const []); setState(() { _allRows = rows; _filteredRows = List>.from(rows); _currentPage = 1; }); } else { setState(() { _allRows = []; _filteredRows = []; }); } } catch (_) { setState(() { _allRows = []; _filteredRows = []; }); } finally { if (mounted) setState(() => _isLoading = false); } } void _filterRows(String query) { final q = query.trim().toLowerCase(); setState(() { _currentPage = 1; if (q.isEmpty) { _filteredRows = List>.from(_allRows); return; } _filteredRows = _allRows.where((item) { return (item['id'] ?? '').toString().toLowerCase().contains(q) || (item['incentive_file_name'] ?? '').toString().toLowerCase().contains(q) || (item['vaild_from'] ?? item['valid_from'] ?? '') .toString() .toLowerCase() .contains(q) || (item['created_by_name'] ?? '').toString().toLowerCase().contains(q) || (item['created_date'] ?? '').toString().toLowerCase().contains(q) || (item['created_at'] ?? '').toString().toLowerCase().contains(q); }).toList(); }); } List> get _pageRows { final list = List>.from(_filteredRows); list.sort((a, b) { final left = int.tryParse(a['id']?.toString() ?? '') ?? 0; final right = int.tryParse(b['id']?.toString() ?? '') ?? 0; return right.compareTo(left); }); if (list.isEmpty) return []; final maxPage = (list.length / _itemsPerPage).ceil(); final safePage = _currentPage.clamp(1, maxPage); final start = (safePage - 1) * _itemsPerPage; final end = (start + _itemsPerPage).clamp(0, list.length); return list.sublist(start, end); } @override Widget build(BuildContext context) { return MainLayout( title: 'Payout List', body: SelectionArea( child: Padding( padding: const EdgeInsets.all(8), child: Column( children: [ Row( children: [ Text('Payout List', style: _titleStyle), const Spacer(), ThemedSearchField( hintText: 'Search', backgroundColor: Colors.white, txtHeight: 34, txtwidth: MediaQuery.of(context).size.width * 0.18, controller: _searchController, onChanged: _filterRows, ), const SizedBox(width: 10), if (_showUploadButton) ElevatedButton.icon( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF2E7D6E), foregroundColor: Colors.white, ), onPressed: () async { final shouldRefresh = await showDialog( context: context, builder: (_) => const UploadGridModal(), ); if (shouldRefresh == true && mounted) { await _loadGridList(); } }, icon: const Icon(Icons.add, size: 18), label: const Text('Upload Payout'), ), ], ), const SizedBox(height: 10), _buildHeader(), Expanded( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _pageRows.isEmpty ? const Center(child: Text('No available data')) : ListView.builder( itemCount: _pageRows.length, itemBuilder: (context, index) { final row = _pageRows[index]; final sno = ((_currentPage - 1) * _itemsPerPage) + index + 1; return _buildRow(context, row, sno); }, ), ), PaginationControls( currentPage: _currentPage, itemsPerPage: _itemsPerPage, totalItems: _filteredRows.length, onPageChanged: (page) => setState(() => _currentPage = page), onItemsPerPageChanged: (items) => setState(() { _itemsPerPage = items; _currentPage = 1; }), ), ], ), ), ), ); } Widget _buildHeader() { return Container( decoration: BoxDecoration( color: const Color(0xFFF1F5F9), borderRadius: BorderRadius.circular(6), ), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: Row( children: [ Expanded(flex: 2, child: Text('Valid From', style: _headerStyle)), Expanded(flex: 4, child: Text('File Name', style: _headerStyle)), Expanded(flex: 2, child: Text('Created By', style: _headerStyle)), Expanded(flex: 2, child: Text('Created Date', style: _headerStyle)), Expanded(flex: 1, child: Text('Action', style: _headerStyle)), ], ), ); } Widget _buildRow(BuildContext context, Map row, int sno) { return Container( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), decoration: const BoxDecoration( color: Colors.white, border: Border(bottom: BorderSide(color: Colors.blueGrey, width: 0.15)), ), child: Row( children: [ Expanded( flex: 2, child: Text( (row['vaild_from'] ?? row['valid_from'] ?? '-').toString(), style: _dataStyle, ), ), Expanded( flex: 4, child: Text( (row['incentive_file_name'] ?? '-').toString(), style: _dataStyle, overflow: TextOverflow.ellipsis, maxLines: 1, ), ), Expanded( flex: 2, child: Text((row['created_by_name'] ?? '-').toString(), style: _dataStyle), ), Expanded( flex: 2, child: Text((row['created_date'] ?? '-').toString(), style: _dataStyle), ), Expanded( flex: 1, child: IconButton( tooltip: 'View', onPressed: () => context.go('${AppRoutes.gridView}?file_id=${row['id']}'), icon: const Icon(Icons.visibility_outlined, size: 18), ), ), ], ), ); } } class GridList extends GridListScreen { const GridList({super.key}); } final _titleStyle = GoogleFonts.poppins(fontSize: 14, fontWeight: FontWeight.w600); final _dataStyle = GoogleFonts.inter(fontSize: 12, fontWeight: FontWeight.w400); final _headerStyle = GoogleFonts.poppins( fontSize: 11.2, fontWeight: FontWeight.w500, color: const Color(0xFF1E293B), );