diff --git a/lib/Screens/allTrips/list_all_plans.dart b/lib/Screens/allTrips/list_all_plans.dart index 90cf818..78b3eee 100644 --- a/lib/Screens/allTrips/list_all_plans.dart +++ b/lib/Screens/allTrips/list_all_plans.dart @@ -79,6 +79,7 @@ class _ListAllPlansState extends State { (plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) || (plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false); }).toList(); + currentPage = 0; }); print("filteredPlans: $filteredPlans"); } diff --git a/lib/Screens/approvals/approval_list.dart b/lib/Screens/approvals/approval_list.dart index 0c1bd35..2d9509b 100644 --- a/lib/Screens/approvals/approval_list.dart +++ b/lib/Screens/approvals/approval_list.dart @@ -324,6 +324,7 @@ class _ApprovalListState extends State { (plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) || (plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false); }).toList(); + currentPage = 0; }); print("filteredPlans: $filteredPlans"); } diff --git a/lib/Screens/costCenter/costCenter_list.dart b/lib/Screens/costCenter/costCenter_list.dart index 57fa433..3d1e878 100644 --- a/lib/Screens/costCenter/costCenter_list.dart +++ b/lib/Screens/costCenter/costCenter_list.dart @@ -153,6 +153,7 @@ class CostCenterListState extends State { (object['description']?.toLowerCase().contains(lowerQuery) ?? false) || (isActiveStatus.contains(lowerQuery)); }).toList(); + currentPage = 0; }); print("filteredCostCenter: $filteredCostCenter"); diff --git a/lib/Screens/department/department_list.dart b/lib/Screens/department/department_list.dart index 086d446..a6c0b5e 100644 --- a/lib/Screens/department/department_list.dart +++ b/lib/Screens/department/department_list.dart @@ -151,6 +151,7 @@ class DepartmentListState extends State { false) || (isActiveStatus.contains(lowerQuery)); }).toList(); + currentPage = 0; }); print("filteredDepartment: $filteredDepartment"); } diff --git a/lib/Screens/forex/forex_list.dart b/lib/Screens/forex/forex_list.dart index 9e0f1b6..bf64c2c 100644 --- a/lib/Screens/forex/forex_list.dart +++ b/lib/Screens/forex/forex_list.dart @@ -295,6 +295,7 @@ class ForexDataListState extends State { (forex['perdiem_amount']?.toLowerCase().contains(lowerQuery) ?? false); }).toList(); + currentPage = 0; }); print("filteredPlans: $filteredForex"); } diff --git a/lib/Screens/group/groupList.dart b/lib/Screens/group/groupList.dart index ab9ef8d..17e205e 100644 --- a/lib/Screens/group/groupList.dart +++ b/lib/Screens/group/groupList.dart @@ -1,19 +1,22 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:frontend/Screens/group/group.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:responsive_builder/responsive_builder.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import '../../config/apiUrl.dart'; import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; +import '../../utils/pagination.dart'; import 'groupDetails.dart'; + + class GroupList extends StatefulWidget { @override _GroupListState createState() => _GroupListState(); @@ -22,18 +25,44 @@ class GroupList extends StatefulWidget { class _GroupListState extends State { final ApiService apiService = ApiService(); - List? apiAllGroups; + late Future> futureGroups; + + late Map groupSingleData; + List? apiCountryData; + String? selectedGroupId; + String? orgId; + Color? layoutColor; Color? bodyColor; + List allGroups = []; + List filteredGroups = []; + TextEditingController searchController = TextEditingController(); + + + int currentPage = 0; + int itemsPerPage = 10; + + List? apiAllGroups; + @override void initState() { super.initState(); + futureGroups = fetchGroups(); + + futureGroups.then((object) { + setState(() { + allGroups = object; + }); + }); WidgetsBinding.instance.addPostFrameCallback((_) { - loadAllGroups(); loadInitialData(); + fetchGroups(); + loadAllGroups(); }); + + // futurePlans = fetchPlans(); } void loadInitialData() async { @@ -41,37 +70,75 @@ class _GroupListState extends State { String? bodyStringColor = await getBodyColor(); setState(() { - layoutColor = layoutString != null + layoutColor = + layoutString != null ? Color(int.parse(layoutString)) : Colors.redAccent; - bodyColor = bodyStringColor != null + bodyColor = + bodyStringColor != null ? Color(int.parse(bodyStringColor)) : Colors.white; }); } + Future getToken() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString('auth_token'); + } + + + + + Future> fetchGroups() async { + final result = await apiService.fetchAllGroup(); + return result; // Returning raw JSON list + } + + Future loadAllGroups() async { try { final result = await apiService.fetchAllGroup(); setState(() { - apiAllGroups = result; + allGroups = result; }); - print("Fetched services: $apiAllGroups"); + print("Fetched services: $allGroups"); } catch (e) { print('Error fetching role list: $e'); } } + void filterGroups(String query) { + print("allGroups before filtering: $query"); + final lowerQuery = query.toLowerCase(); + + setState(() { + filteredGroups = + allGroups.where((group) { + return (group['name']?.toLowerCase().contains(lowerQuery) ?? + false) || + (group['domestic_policy_name']?.toLowerCase().contains(lowerQuery) ?? + false) + (group['international_policy_name']?.toLowerCase().contains(lowerQuery) ?? + false) || + (group['description']?.toLowerCase().contains(lowerQuery) ?? + false) || + (group['is_active']?.toLowerCase().contains(lowerQuery) ?? false);}).toList(); + currentPage = 0; + }); + + print("filtered: $filteredGroups"); + } + void handleActiveStatus( - Map groupData, - String groupId, - String currentStatus, - ) async { - print("Toggling user status - $groupId (Current: $currentStatus)"); + Map groupData, + String groupId, + String currentStatus, + ) async { + print("Toggling group status - $groupId (Current: $currentStatus)"); final String apiUrlData = - '$apiUrl/api/groups/update/$groupId'; // API for updating user + '$apiUrl/api/groups/update/$groupId'; // API for updating group final String? token = await getToken(); if (token == null) { @@ -97,14 +164,14 @@ class _GroupListState extends State { ); if (response.statusCode == 200 || response.statusCode == 201) { - print("User status updated successfully to $newStatus!"); - loadAllGroups(); // Refresh users list after update + print("Group status updated successfully to $newStatus!"); + loadAllGroups(); // Refresh groups list after update } else { - print("Failed to update user status. Status: ${response.statusCode}"); + print("Failed to update group status. Status: ${response.statusCode}"); print("Error: ${response.body}"); } } catch (e) { - print("Error updating user status: $e"); + print("Error updating group status: $e"); } } @@ -122,49 +189,45 @@ class _GroupListState extends State { loadAllGroups(); } - // Future deleteGroupFromApi(int groupId) async { - // try { - // await apiService.deleteGroup(groupId); // your delete API call - // deleteGroup(groupId); // remove from UI list - // } catch (e) { - // print('Error deleting group: $e'); - // } - // }' @override Widget build(BuildContext context) { - return ResponsiveBuilder(builder: (context, sizingInfo) { - bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + return ResponsiveBuilder( + builder: (context, sizingInfo) { + bool isDesktop = + sizingInfo.deviceScreenType == DeviceScreenType.desktop; - return Scaffold( - // backgroundColor: Colors.white, - backgroundColor: Color(0xFFf5f5f5), - appBar: CustomAppBar(isDesktop: isDesktop), - drawer: CustomDrawer(isDesktop: false), - body: Padding( - padding: isDesktop - ? EdgeInsets.symmetric( - horizontal: MediaQuery.of(context).size.width * - 0.1, // 30% of screen width as horizontal padding - vertical: MediaQuery.of(context).size.height * - 0, // 5% of screen height as vertical padding - ) - : EdgeInsets.all(8), - child: Row( - children: [ - // if (isDesktop) CustomDrawer(isDesktop: true), - Expanded(child: buildGroupListLayout(isDesktop)) - ], + return Scaffold( + backgroundColor: Color(0xFFf5f5f5), + appBar: CustomAppBar(isDesktop: isDesktop), + drawer: CustomDrawer(isDesktop: false), + body: Padding( + padding: + isDesktop + ? EdgeInsets.symmetric( + horizontal: + MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: + MediaQuery.of(context).size.height * + 0, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(0), + child: Row( + children: [ + Expanded(child: buildGroupList(isDesktop)), + ], + ), ), - ), - ); - }); + ); + }, + ); } - Widget buildGroupListLayout(bool isDesktop) { + Widget buildGroupList(bool isDesktop) { return Container( margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null, - padding: const EdgeInsets.all(10), + padding: const EdgeInsets.all(1), decoration: BoxDecoration( color: isDesktop ? Colors.white : Color(0xFFFCFCFC), ), @@ -176,258 +239,689 @@ class _GroupListState extends State { // color: Colors.white, // // color: Color(0xFFF7F7FB), // width: 3.5)), - child: buildGroupData(isDesktop), + child: buildGroupTable(isDesktop), ); } - // Widget buildGroupListView(bool isDesktop) { - // return Container( - // child: Text("DAta"), - // ); - // } - - Widget buildGroupData(isDesktop) { + Widget buildGroupTable(bool isDesktop) { return Container( // margin: isDesktop // ? EdgeInsets.all(10.0) // : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0), // padding: const EdgeInsets.all(10), - height: isDesktop + height: + isDesktop ? MediaQuery.of(context).size.height * 0.98 : MediaQuery.of(context).size.height, - // decoration: BoxDecoration( - // border: isDesktop - // ? Border.all( - // width: 2, - // color: Colors.white, - // // color: Color(0xFFF7F7FB), - // ) - // : null, - // color: Colors.white, - // // color: Color(0xFFF7F7FB), - // - // // color: Colors.amber, - // ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Container( + color: Colors.white, + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + // Divider( + // thickness: 0.2, // how "thick" the line is + // color: Colors.grey, // optional + // ), Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'Group List', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, + Row( + children: [ + Text( + 'Group', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ], + ), + if (isDesktop) + SizedBox(width: MediaQuery.of(context).size.width * 0.28), + + if (isDesktop) + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchController, + onChanged: filterGroups, + decoration: InputDecoration( + hintText: "Search for a Group", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), ), - ), - IconButton( - icon: const Icon(Icons.keyboard_arrow_down), - onPressed: () {}, - ), - ], - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - // side: BorderSide(color: , width: 1), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: () async { - // List users = await futureUsers; - // context.go('/CreateGroup'); - showDialog( - context: context, - builder: (context) => GroupData( - isDesktop: isDesktop, - groupId: null, - layoutColor: layoutColor!, - fetchGetGroup: refreshData + // SizedBox(width: 16), + Spacer(), + + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + foregroundColor: Colors.white, + disabledBackgroundColor: Color(0xFF114D8B), + disabledForegroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), ), - ); + onPressed: () async { + // List groups = await futureGroups; + // context.go('/CreateGroup'); + showDialog( + context: context, + builder: (context) => GroupData( + isDesktop: isDesktop, + groupId: null, + layoutColor: layoutColor!, + fetchGetGroup: refreshData + ), + ); - }, - child: Row( - children: [ - Text('New Group', style: GoogleFonts.poppins(fontSize: 12)), - SizedBox( - width: 5, - ), - Icon( - Icons.add_circle_outline_rounded, - color: Colors.white, - ), - ], - ), - ), - ], - ), - SizedBox( - height: 5, - ), - Row( - children: [ - Expanded( - child: Container( - height: MediaQuery.of(context).size.height * 0.75, - padding: const EdgeInsets.all(10), - // margin: const EdgeInsets.only(bottom: 10), - color: Colors.white, - // color: Colors.red.shade100, - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely children: [ - buildGroupListView(isDesktop), + Text( + "Add New Group", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon( + Icons.add_circle_outline_rounded, + size: 15, + color: Colors.white, + ), ], ), ), - ), + ], + ), + + if (!isDesktop) SizedBox(height: 5), + isDesktop + ? SizedBox.shrink() + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.8, + height: 35, + child: TextField( + controller: searchController, + onChanged: filterGroups, + decoration: InputDecoration( + hintText: "Search for a Group", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + // SizedBox(width: 16), + ], + ), + const SizedBox(height: 10), + FutureBuilder>( + future: futureGroups, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError || + !snapshot.hasData || + snapshot.data!.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 8), + Text( + "No Group Found", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ), + const SizedBox(height: 20), + Text( + "Please Create Group", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 16, + color: Colors.grey, + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } + + List groups = + filteredGroups.isNotEmpty ? filteredGroups : allGroups; + + groups.sort((a, b) { + DateTime dateA = DateTime.parse(a['created_on']); + DateTime dateB = DateTime.parse(b['created_on']); + + return dateB.compareTo(dateA); // Descending: newest first + }); + + List paginatedGroup = + groups + .skip(currentPage * itemsPerPage) + .take(itemsPerPage) + .toList(); + + Widget table = LayoutBuilder( + builder: (context, constraints) { + double minWidth = isDesktop ? constraints.maxWidth : 1300; + + return ConstrainedBox( + constraints: BoxConstraints(minWidth: minWidth), + child: DataTable( + dividerThickness: 0.5, + columnSpacing: isDesktop ? 24.0 : 16.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, + color: Colors.grey.shade200, + ), + ), + columns: [ + DataColumn( + label: Text( + 'Group Name', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Domestic Policy', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'International Policy', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Description', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Actions', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + rows: + paginatedGroup.map((group) { + String groupId = + group['group_id'].toString(); // Get group ID + bool isSelected = selectedGroupId == groupId; + + return DataRow( + cells: [ + DataCell( + Text( + "${group['name'] ?? ''}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text("${group['domestic_policy_name'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + "${group['international_policy_name'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + "${group['description'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + group['is_active'] == "1" + ? "Active" + : "Inactive", + style: TextStyle( + color: + group['is_active'] == "1" + ? Colors.green + : Colors.grey, + fontFamily: "Inter", + fontWeight: FontWeight.w400, + ), + ), + ), + DataCell( + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + GestureDetector( + onTap: () async { + if (group['group_id'] != null) { + final newGroupID = int.tryParse( + group['group_id'].toString()); + if (newGroupID != null) { + final data = await apiService.getGroupDetailsFind( + newGroupID); // ✅ Always an int + showDialog( + context: context, + builder: (context) => + GroupData( + isDesktop: isDesktop, + groupId: newGroupID, + // Pass the ID + groupData: data, + layoutColor: layoutColor!, + fetchGetGroup: refreshData + ), + ); + } + } else { + print("something went wrong check properly"); + } + }, + + // onTap: () { + // context.go("/CreateGroup", extra: group); + // }, + child: Tooltip( + message: 'Edit Group Details', + child: Image.asset('assets/images/IconsImg/edit.png', + width: 20, height: 15), ), + ), + SizedBox( + width: 5, + ), + GestureDetector( + onTap: () { + final idStr = group['group_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("group_id is null"); + return; + } + final status = group['is_active']; + // print("GroupId : ${group['group_id']} "); + deleteGroup(group, id, status); + }, + child: Tooltip( + message: 'Delete Group Details', + child: Image.asset('assets/images/IconsImg/delete.png', + width: 20, height: 15),), + ), + ], + ), + ), + ], + ); + }).toList(), + ), + ); + }, + ); + Widget buildMobileCardView(List paginatedGroup) { + return ListView.builder( + itemCount: paginatedGroup.length, + itemBuilder: (context, index) { + final object = paginatedGroup[index]; + + return Card( + color: Colors.white, + margin: EdgeInsets.symmetric(horizontal: 12, vertical: 6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 3, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Row 1: Policy Name and Actions + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.black, + ), + children: [ + TextSpan( + text: "Group Name: ", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + TextSpan( + text: "${object['name'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + fontWeight: FontWeight.normal + ), + ), + ], + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () async { + if (object['group_id'] != null) { + final newGroupID = int.tryParse( + object['group_id'].toString()); + if (newGroupID != null) { + final data = await apiService.getGroupDetailsFind( + newGroupID); // ✅ Always an int + showDialog( + context: context, + builder: (context) => + GroupData( + isDesktop: isDesktop, + groupId: newGroupID, + // Pass the ID + groupData: data, + layoutColor: layoutColor!, + fetchGetGroup: refreshData + ), + ); + } + } else { + print("something went wrong check properly"); + } + }, + + // onTap: () { + // context.go("/CreateGroup", extra: group); + // }, + child: Tooltip( message: 'Edit Group Details', + child: Image.asset('assets/images/IconsImg/edit.png', + width: 20, height: 15),), + ), + SizedBox( + width: 5, + ), + GestureDetector( + onTap: () { + final idStr = object['group_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("group_id is null"); + return; + } + final status = object['is_active']; + // print("GroupId : ${group['group_id']} "); + deleteGroup(object, id, status); + }, + child: Tooltip( + message: 'Edit Group Details', + child: Image.asset('assets/images/IconsImg/delete.png', + width: 20, height: 15),), + ), + ], + ), + ], + ), + + SizedBox(height: 8), // Spacing + + // Row 2: + RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.black, + ), + children: [ + TextSpan( + text: "Domestic Policy: ", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + TextSpan( + text: "${object['domestic_policy_name'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + fontWeight: FontWeight.normal + ), + ), + ], + ), + ), + SizedBox(height: 8), // Spacing + + // Row 3: + RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.black, + ), + children: [ + TextSpan( + text: "International Policy: ", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + TextSpan( + text: "${object['international_policy_name']}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + fontWeight: FontWeight.normal + ), + ), + ], + ), + ), + SizedBox(height: 8), // Spacing + + // Row 4: + RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.black, + ), + children: [ + TextSpan( + text: "Description: ", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + TextSpan( + text: "${object['description'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + fontWeight: FontWeight.normal + ), + ), + ], + ), + ), + ], + ), + ), + ); + }, + ); + } + + return Expanded( + child: Column( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: + isDesktop + ? SingleChildScrollView( + scrollDirection: Axis.vertical, + child: table, // <-- your existing table + ) + : buildMobileCardView(paginatedGroup), + ), + PaginationControls( + currentPage: currentPage, + itemsPerPage: itemsPerPage, + totalItems: groups.length, + activeColor: layoutColor, // your theme color + onPageChanged: (page) { + setState(() { + currentPage = page; + }); + }, + onItemsPerPageChanged: (items) { + setState(() { + itemsPerPage = items; + currentPage = 0; + }); + }, + ), + ], + ), + ); + }, ), ], - ) - ], + ), + ), ), ); } - - Widget buildGroupListView(bool isDesktop) { - if (apiAllGroups == null || apiAllGroups!.isEmpty) { - return Center(child: Text("No groups found.")); - } - - return ListView.builder( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: apiAllGroups!.length, - itemBuilder: (context, index) { - final group = apiAllGroups![index]; - return Card( - // color: bodyColor, - // color: Color(0xFFF5F5F5), - color: Colors.white, - margin: EdgeInsets.symmetric(vertical: 6, horizontal: 10), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text("Group Name", - style: GoogleFonts.poppins( - fontSize: 11.5, fontWeight: FontWeight.w400)), - ), - Expanded( - child: Text("Domestic Policy", - style: GoogleFonts.poppins( - fontSize: 11.5, fontWeight: FontWeight.w400)), - ), - Expanded( - child: Text("International Policy", - style: GoogleFonts.poppins( - fontSize: 11.5, fontWeight: FontWeight.w400)), - ), - Expanded( - child: Text("Description", - style: GoogleFonts.poppins( - fontSize: 11.5, fontWeight: FontWeight.w400)), - ), - ], - ), - SizedBox(height: 4), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text("${group['name']}", - style: GoogleFonts.poppins( - fontSize: 13, fontWeight: FontWeight.w600)), - ), - Expanded( - child: Text("${group['domestic_policy_name'] ?? 'N/A'}", - style: GoogleFonts.poppins( - fontSize: 13, fontWeight: FontWeight.w600)), - ), - Expanded( - child: Text("${group['international_policy_name']}", - style: GoogleFonts.poppins( - fontSize: 13, fontWeight: FontWeight.w600))), - Expanded( - child: Text("${group['description'] ?? 'N/A'}", - style: GoogleFonts.poppins( - fontSize: 13, fontWeight: FontWeight.w600))), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - GestureDetector( - onTap: () async { - if (group['group_id'] != null) { - final newGroupID = int.tryParse( - group['group_id'].toString()); - if (newGroupID != null) { - final data = await apiService.getGroupDetailsFind( - newGroupID); // ✅ Always an int - showDialog( - context: context, - builder: (context) => - GroupData( - isDesktop: isDesktop, - groupId: newGroupID, - // Pass the ID - groupData: data, - layoutColor: layoutColor!, - fetchGetGroup: refreshData - ), - ); - } - } else { - print("something went wrong check properly"); - } - }, - - // onTap: () { - // context.go("/CreateGroup", extra: group); - // }, - child: Image.asset('assets/images/IconsImg/edit.png', - width: 20, height: 15), - ), - SizedBox( - width: 5, - ), - GestureDetector( - onTap: () { - final idStr = group['group_id']; - final id = int.tryParse(idStr.toString()); - - if (id == null) { - print("group_id is null"); - return; - } - final status = group['is_active']; - // print("GroupId : ${group['group_id']} "); - deleteGroup(group, id, status); - }, - child: Image.asset('assets/images/IconsImg/delete.png', - width: 20, height: 15), - ), - ], - ), - ], - ), - ), - ); - }, - ); - } -} +} \ No newline at end of file diff --git a/lib/Screens/group/groupListBackUp.dart b/lib/Screens/group/groupListBackUp.dart new file mode 100644 index 0000000..ab02409 --- /dev/null +++ b/lib/Screens/group/groupListBackUp.dart @@ -0,0 +1,433 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:frontend/Screens/group/group.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:responsive_builder/responsive_builder.dart'; + +import '../../config/apiUrl.dart'; +import '../../routes/custom_appBar.dart'; +import '../../routes/custom_drawer.dart'; +import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; +import 'groupDetails.dart'; + +class GroupListBackUp extends StatefulWidget { + @override + _GroupListBackUpState createState() => _GroupListBackUpState(); +} + +class _GroupListBackUpState extends State { + final ApiService apiService = ApiService(); + + List? apiAllGroups; + Color? layoutColor; + Color? bodyColor; + + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + loadAllGroups(); + loadInitialData(); + }); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + bodyColor = bodyStringColor != null + ? Color(int.parse(bodyStringColor)) + : Colors.white; + }); + } + + Future loadAllGroups() async { + try { + final result = await apiService.fetchAllGroup(); + setState(() { + apiAllGroups = result; + }); + print("Fetched services: $apiAllGroups"); + } catch (e) { + print('Error fetching role list: $e'); + } + } + + void handleActiveStatus( + Map groupData, + String groupId, + String currentStatus, + ) async { + print("Toggling user status - $groupId (Current: $currentStatus)"); + + final String apiUrlData = + '$apiUrl/api/groups/update/$groupId'; // API for updating user + final String? token = await getToken(); + + if (token == null) { + print("Error: Token not found"); + return; + } + + // Toggle status: If active ("1"), set to inactive ("0"); otherwise, activate ("1") + String newStatus = (currentStatus == "1") ? "0" : "1"; + + print("STatus 1 - $newStatus"); + + try { + final response = await http.put( + Uri.parse(apiUrlData), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode({ + "is_active": newStatus // Set new status dynamically + }), + ); + + if (response.statusCode == 200 || response.statusCode == 201) { + print("User status updated successfully to $newStatus!"); + loadAllGroups(); // Refresh users list after update + } else { + print("Failed to update user status. Status: ${response.statusCode}"); + print("Error: ${response.body}"); + } + } catch (e) { + print("Error updating user status: $e"); + } + } + + void deleteGroup(Map groupdata, groupId, status) { + print("GroupId : $groupId"); + print("Groupstatus: $status"); + print("GroupsData: $groupdata"); + + // handleActiveStatus(groupdata, groupId, status); + print("Calling handleActiveStatus with: id=$groupId, status=$status"); + handleActiveStatus(groupdata, groupId.toString(), status.toString()); + } + + Future refreshData() async { + loadAllGroups(); + } + + // Future deleteGroupFromApi(int groupId) async { + // try { + // await apiService.deleteGroup(groupId); // your delete API call + // deleteGroup(groupId); // remove from UI list + // } catch (e) { + // print('Error deleting group: $e'); + // } + // }' + + @override + Widget build(BuildContext context) { + return ResponsiveBuilder(builder: (context, sizingInfo) { + bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; + + return Scaffold( + // backgroundColor: Colors.white, + backgroundColor: Color(0xFFf5f5f5), + appBar: CustomAppBar(isDesktop: isDesktop), + drawer: CustomDrawer(isDesktop: false), + body: Padding( + padding: isDesktop + ? EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: MediaQuery.of(context).size.height * + 0, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(8), + child: Row( + children: [ + // if (isDesktop) CustomDrawer(isDesktop: true), + Expanded(child: buildGroupListLayout(isDesktop)) + ], + ), + ), + ); + }); + } + + Widget buildGroupListLayout(bool isDesktop) { + return Container( + margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: isDesktop ? Colors.white : Color(0xFFFCFCFC), + ), + // decoration: BoxDecoration( + // // color: Colors.amber, + // // color: bodyColor, + // color: Color(0xFFE1F5FE), + // border: Border.all( + // color: Colors.white, + // // color: Color(0xFFF7F7FB), + // width: 3.5)), + child: buildGroupData(isDesktop), + ); + } + + // Widget buildGroupListView(bool isDesktop) { + // return Container( + // child: Text("DAta"), + // ); + // } + + Widget buildGroupData(isDesktop) { + return Container( + // margin: isDesktop + // ? EdgeInsets.all(10.0) + // : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0), + // padding: const EdgeInsets.all(10), + height: isDesktop + ? MediaQuery.of(context).size.height * 0.98 + : MediaQuery.of(context).size.height, + // decoration: BoxDecoration( + // border: isDesktop + // ? Border.all( + // width: 2, + // color: Colors.white, + // // color: Color(0xFFF7F7FB), + // ) + // : null, + // color: Colors.white, + // // color: Color(0xFFF7F7FB), + // + // // color: Colors.amber, + // ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + 'Group List', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + IconButton( + icon: const Icon(Icons.keyboard_arrow_down), + onPressed: () {}, + ), + ], + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: , width: 1), + ), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + onPressed: () async { + // List users = await futureUsers; + // context.go('/CreateGroup'); + showDialog( + context: context, + builder: (context) => GroupData( + isDesktop: isDesktop, + groupId: null, + layoutColor: layoutColor!, + fetchGetGroup: refreshData + ), + ); + + + }, + child: Row( + children: [ + Text('New Group', style: GoogleFonts.poppins(fontSize: 12)), + SizedBox( + width: 5, + ), + Icon( + Icons.add_circle_outline_rounded, + color: Colors.white, + ), + ], + ), + ), + ], + ), + SizedBox( + height: 5, + ), + Row( + children: [ + Expanded( + child: Container( + height: MediaQuery.of(context).size.height * 0.75, + padding: const EdgeInsets.all(10), + // margin: const EdgeInsets.only(bottom: 10), + color: Colors.white, + // color: Colors.red.shade100, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + children: [ + buildGroupListView(isDesktop), + ], + ), + ), + ), + ), + ], + ) + ], + ), + ); + } + + Widget buildGroupListView(bool isDesktop) { + if (apiAllGroups == null || apiAllGroups!.isEmpty) { + return Center(child: Text("No groups found.")); + } + + return ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: apiAllGroups!.length, + itemBuilder: (context, index) { + final group = apiAllGroups![index]; + return Card( + // color: bodyColor, + // color: Color(0xFFF5F5F5), + color: Colors.white, + margin: EdgeInsets.symmetric(vertical: 6, horizontal: 10), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text("Group Name", + style: GoogleFonts.poppins( + fontSize: 11.5, fontWeight: FontWeight.w400)), + ), + Expanded( + child: Text("Domestic Policy", + style: GoogleFonts.poppins( + fontSize: 11.5, fontWeight: FontWeight.w400)), + ), + Expanded( + child: Text("International Policy", + style: GoogleFonts.poppins( + fontSize: 11.5, fontWeight: FontWeight.w400)), + ), + Expanded( + child: Text("Description", + style: GoogleFonts.poppins( + fontSize: 11.5, fontWeight: FontWeight.w400)), + ), + ], + ), + SizedBox(height: 4), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text("${group['name']}", + style: GoogleFonts.poppins( + fontSize: 13, fontWeight: FontWeight.w600)), + ), + Expanded( + child: Text("${group['domestic_policy_name'] ?? 'N/A'}", + style: GoogleFonts.poppins( + fontSize: 13, fontWeight: FontWeight.w600)), + ), + Expanded( + child: Text("${group['international_policy_name']}", + style: GoogleFonts.poppins( + fontSize: 13, fontWeight: FontWeight.w600))), + Expanded( + child: Text("${group['description'] ?? 'N/A'}", + style: GoogleFonts.poppins( + fontSize: 13, fontWeight: FontWeight.w600))), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () async { + if (group['group_id'] != null) { + final newGroupID = int.tryParse( + group['group_id'].toString()); + if (newGroupID != null) { + final data = await apiService.getGroupDetailsFind( + newGroupID); // ✅ Always an int + showDialog( + context: context, + builder: (context) => + GroupData( + isDesktop: isDesktop, + groupId: newGroupID, + // Pass the ID + groupData: data, + layoutColor: layoutColor!, + fetchGetGroup: refreshData + ), + ); + } + } else { + print("something went wrong check properly"); + } + }, + + // onTap: () { + // context.go("/CreateGroup", extra: group); + // }, + child: Image.asset('assets/images/IconsImg/edit.png', + width: 20, height: 15), + ), + SizedBox( + width: 5, + ), + GestureDetector( + onTap: () { + final idStr = group['group_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("group_id is null"); + return; + } + final status = group['is_active']; + // print("GroupId : ${group['group_id']} "); + deleteGroup(group, id, status); + }, + child: Image.asset('assets/images/IconsImg/delete.png', + width: 20, height: 15), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/Screens/hotels/hotels_list.dart b/lib/Screens/hotels/hotels_list.dart index 9858dc9..c23a904 100644 --- a/lib/Screens/hotels/hotels_list.dart +++ b/lib/Screens/hotels/hotels_list.dart @@ -200,6 +200,7 @@ class HotelsDataListState extends State { false) || (isActiveStatus.contains(lowerQuery)); }).toList(); + currentPage = 0; }); print("filteredHotels: $filteredHotels"); } diff --git a/lib/Screens/plans/list_plans.dart b/lib/Screens/plans/list_plans.dart index bf1a68d..afae4f3 100644 --- a/lib/Screens/plans/list_plans.dart +++ b/lib/Screens/plans/list_plans.dart @@ -106,6 +106,7 @@ class _ListPlansState extends State { (plan.createdOn?.toLowerCase().contains(lowerQuery) ?? false) || (plan.statusValue?.toLowerCase().contains(lowerQuery) ?? false); }).toList(); + currentPage = 0; }); print("filteredPlans: $filteredPlans"); } diff --git a/lib/Screens/policy/policyListBackup.dart b/lib/Screens/policy/policyListBackup.dart new file mode 100644 index 0000000..2abe9b9 --- /dev/null +++ b/lib/Screens/policy/policyListBackup.dart @@ -0,0 +1,428 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:frontend/Screens/group/group.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:http/http.dart' as http; +import 'package:responsive_builder/responsive_builder.dart'; + +import '../../config/apiUrl.dart'; +import '../../routes/custom_appBar.dart'; +import '../../routes/custom_drawer.dart'; +import '../../services/apiService.dart'; +import '../../utils/auth_utils.dart'; + +class PolicyListBackup extends StatefulWidget { + @override + _PolicyListBackupState createState() => _PolicyListBackupState(); +} + +class _PolicyListBackupState extends State { + final ApiService apiService = ApiService(); + + List? apiAllGroups; + Color? layoutColor; + Color? bodyColor; + + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + loadAllGroups(); + loadInitialData(); + }); + } + + void loadInitialData() async { + String? layoutString = await getLayoutColor(); + String? bodyStringColor = await getBodyColor(); + + setState(() { + layoutColor = + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; + + bodyColor = + bodyStringColor != null + ? Color(int.parse(bodyStringColor)) + : Colors.white; + }); + } + + Future loadAllGroups() async { + try { + final result = await apiService.fetchAllPolicy(); + + // Sort by policy_id descending (latest first) + result.sort((a, b) { + int idA = int.tryParse(a['policy_id'].toString()) ?? 0; + int idB = int.tryParse(b['policy_id'].toString()) ?? 0; + return idB.compareTo(idA); // latest first + }); + + setState(() { + apiAllGroups = result; + }); + print("Fetched services: $apiAllGroups"); + } catch (e) { + print('Error fetching role list: $e'); + } + } + + void handleActiveStatus( + Map policyData, + String policyId, + String currentStatus, + ) async { + print("Toggling user status - $policyId (Current: $currentStatus)"); + + final String apiUrlData = + '$apiUrl/api/policy/createOrUpdate'; // API for updating user + final String? token = await getToken(); + + if (token == null) { + print("Error: Token not found"); + return; + } + + // Toggle status: If active ("1"), set to inactive ("0"); otherwise, activate ("1") + String newStatus = (currentStatus == "1") ? "0" : "1"; + + print("STatus 1 - $newStatus"); + + final int? selectedPolicyId; + + if (policyId.isNotEmpty) { + selectedPolicyId = int.tryParse(policyId); + policyData['policy_id'] = selectedPolicyId; // Add only if updating + policyData['is_active'] = newStatus; // Add only if updating + } + + try { + final response = await http.post( + Uri.parse(apiUrlData), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: jsonEncode(policyData), // Convert map to JSON + ); + + if (response.statusCode == 200) { + print("policyData submitted successfully!"); + print("Response: ${response.body}"); + + loadAllGroups(); + } else { + print("Failed to submit policyData. Status: ${response.statusCode}"); + print("Error: ${response.body}"); + } + } catch (e) { + print(" Error submitting policyData: $e"); + } + } + + void deletePolicy(Map policydata, policyId, status) { + print("policyId : $policyId"); + print("policystatus: $status"); + print("policysData: $policydata"); + + // handleActiveStatus(groupdata, groupId, status); + print("Calling handleActiveStatus with: id=$policyId, status=$status"); + handleActiveStatus(policydata, policyId.toString(), status.toString()); + } + + // Future deleteGroupFromApi(int groupId) async { + // try { + // await apiService.deleteGroup(groupId); // your delete API call + // deleteGroup(groupId); // remove from UI list + // } catch (e) { + // print('Error deleting group: $e'); + // } + // }' + + @override + Widget build(BuildContext context) { + return ResponsiveBuilder( + builder: (context, sizingInfo) { + bool isDesktop = + sizingInfo.deviceScreenType == DeviceScreenType.desktop; + + return Scaffold( + backgroundColor: Color(0xFFf5f5f5), + appBar: CustomAppBar(isDesktop: isDesktop), + drawer: CustomDrawer(isDesktop: false), + body: Padding( + padding: + isDesktop + ? EdgeInsets.symmetric( + horizontal: + MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: + MediaQuery.of(context).size.height * + 0, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(0), + child: Row( + children: [ + // if (isDesktop) CustomDrawer(isDesktop: true), + Expanded(child: buildGroupList(isDesktop)), + ], + ), + ), + ); + }, + ); + } + + Widget buildGroupList(bool isDesktop) { + return Container( + margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null, + padding: const EdgeInsets.only(left: 10, right: 10, top: 8), + decoration: BoxDecoration( + color: isDesktop ? Colors.white : Color(0xFFFCFCFC), + ), + // decoration: BoxDecoration( + // // color: Colors.amber, + // color: Color(0xFFE1F5FE), + // // color: bodyColor, + // border: Border.all( + // // color: Color(0xFFF7F7FB), + // color: Colors.white, + // width: 3.5)), + child: buildGroupListLayout(isDesktop), + ); + } + + Widget buildGroupListLayout(bool isDesktop) { + return Container( + // margin: isDesktop + // ? EdgeInsets.all(10.0) + // : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0), + // padding: const EdgeInsets.all(10), + height: + isDesktop + ? MediaQuery.of(context).size.height * 0.98 + : MediaQuery.of(context).size.height, + // decoration: BoxDecoration( + // border: isDesktop + // ? Border.all( + // width: 2, + // color: Colors.white, + // // color: Color(0xFFF7F7FB), + // ) + // : null, + // color: Colors.white, + // // color: Color(0xFFF7F7FB), + // + // // color: Colors.amber, + // ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + 'Policy List', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + IconButton( + icon: const Icon(Icons.keyboard_arrow_down), + onPressed: () {}, + ), + ], + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: Color(0xFF114D8B), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + // side: BorderSide(color: , width: 1), + ), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), + ), + onPressed: () async { + // List users = await futureUsers; + context.go('/Policy'); + }, + child: Row( + children: [ + Text( + 'New Policy', + style: GoogleFonts.poppins(fontSize: 12), + ), + SizedBox(width: 5), + Icon(Icons.add_circle_outline_rounded, color: Colors.white), + ], + ), + ), + ], + ), + SizedBox(height: 5), + Row( + children: [ + Expanded( + child: Container( + height: MediaQuery.of(context).size.height * 0.8, + padding: const EdgeInsets.all(10), + // margin: const EdgeInsets.only(bottom: 10), + color: Colors.white, + // color: Colors.red.shade100, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column(children: [buildGroupListView(isDesktop)]), + ), + ), + ), + ], + ), + ], + ), + ); + } + + // Widget buildGroupListView(bool isDesktop) { + // return Container( + // child: Text("DAta"), + // ); + // } + + Widget buildGroupListView(bool isDesktop) { + if (apiAllGroups == null || apiAllGroups!.isEmpty) { + return Center(child: Text("No Policy Found.")); + } + + return ListView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: apiAllGroups!.length, + itemBuilder: (context, index) { + final policy = apiAllGroups![index]; + return Card( + // color: bodyColor, + // color: Color(0xFFF5F5F5), + color: Colors.white, + margin: EdgeInsets.symmetric(vertical: 6, horizontal: 10), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + flex: 1, + child: Text( + "Policy Name", + style: GoogleFonts.poppins( + fontSize: 11.5, + fontWeight: FontWeight.w400, + ), + ), + ), + Expanded( + flex: 1, + child: Text( + "Policy Type", + style: GoogleFonts.poppins( + fontSize: 11.5, + fontWeight: FontWeight.w400, + ), + ), + ), + // Expanded(flex: 1, child: Text("${policy['created_by']}")), + ], + ), + SizedBox(height: 4), + Row( + children: [ + Expanded( + flex: 1, + child: Text( + "${policy['name']}", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + Expanded( + flex: 1, + child: Text( + policy['domestic'] == "1" + ? "Domestic" + : "International", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + // Expanded(flex: 1, child: Text("${policy['created_by']}")), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () async { + final rawId = policy['policy_id']; + final intPolicyId = + rawId is int + ? rawId + : int.tryParse(rawId.toString()) ?? 0; + + Map policyData = await apiService + .getSinglePolicy(intPolicyId); + + print("PolicyDATa: $policyData"); + + context.go("/Policy", extra: policyData); + }, + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + SizedBox(width: 5), + GestureDetector( + onTap: () { + final idStr = policy['policy_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("group_id is null"); + return; + } + final status = policy['is_active']; + + deletePolicy(policy, id, status); + }, + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/Screens/policy/policy_list.dart b/lib/Screens/policy/policy_list.dart index 99c0d1e..4c8ece3 100644 --- a/lib/Screens/policy/policy_list.dart +++ b/lib/Screens/policy/policy_list.dart @@ -1,17 +1,19 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:frontend/Screens/group/group.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:http/http.dart' as http; import 'package:responsive_builder/responsive_builder.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import '../../config/apiUrl.dart'; import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; import '../../services/apiService.dart'; import '../../utils/auth_utils.dart'; +import '../../utils/pagination.dart'; + class PolicyList extends StatefulWidget { @override @@ -19,20 +21,45 @@ class PolicyList extends StatefulWidget { } class _PolicyListState extends State { - final ApiService apiService = ApiService(); - List? apiAllGroups; + final ApiService apiService = ApiService(); + late Future> futurePolicy; + + late Map userSingleData; + List? apiCountryData; + String? selectedPolicyId; + String? orgId; + Color? layoutColor; Color? bodyColor; + List allPolicy = []; + List filteredPolicy = []; + TextEditingController searchController = TextEditingController(); + + + int currentPage = 0; + int itemsPerPage = 10; + + List? apiAllPolicy; + @override void initState() { super.initState(); + futurePolicy = fetchPolicy(); + + futurePolicy.then((object) { + setState(() { + allPolicy = object; + }); + }); WidgetsBinding.instance.addPostFrameCallback((_) { - loadAllGroups(); loadInitialData(); + fetchPolicy(); }); + + // futurePlans = fetchPlans(); } void loadInitialData() async { @@ -41,42 +68,60 @@ class _PolicyListState extends State { setState(() { layoutColor = - layoutString != null - ? Color(int.parse(layoutString)) - : Colors.redAccent; + layoutString != null + ? Color(int.parse(layoutString)) + : Colors.redAccent; bodyColor = - bodyStringColor != null - ? Color(int.parse(bodyStringColor)) - : Colors.white; + bodyStringColor != null + ? Color(int.parse(bodyStringColor)) + : Colors.white; }); } - Future loadAllGroups() async { - try { - final result = await apiService.fetchAllPolicy(); - - // Sort by policy_id descending (latest first) - result.sort((a, b) { - int idA = int.tryParse(a['policy_id'].toString()) ?? 0; - int idB = int.tryParse(b['policy_id'].toString()) ?? 0; - return idB.compareTo(idA); // latest first - }); - - setState(() { - apiAllGroups = result; - }); - print("Fetched services: $apiAllGroups"); - } catch (e) { - print('Error fetching role list: $e'); - } + Future getToken() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString('auth_token'); } + + + Future> fetchPolicy() async { + final data = await apiService.fetchAllPolicy(); + return data; // Returning raw JSON list + } + + // Refresh user list after update + void refreshPolicyList() { + setState(() { + futurePolicy = fetchPolicy(); // Re-fetch users after status update + // Wait for futurePlans to be fetched and update allPlans + }); + } + + void filterPolicy(String query) { + print("allPolicy before filtering: $query"); + final lowerQuery = query.toLowerCase(); + setState(() { + filteredPolicy = + allPolicy.where((object) { + return (object['name']?.toLowerCase().contains(lowerQuery) ?? + false) || + (object['policy_type']?.toLowerCase().contains(lowerQuery) ?? + false) || + (object['is_active']?.toLowerCase().contains(lowerQuery) ?? false);}).toList(); + currentPage = 0; + }); + print("filtered: $filteredPolicy"); + } + + + void handleActiveStatus( - Map policyData, - String policyId, - String currentStatus, - ) async { + Map policyData, + String policyId, + String currentStatus, + ) async { print("Toggling user status - $policyId (Current: $currentStatus)"); final String apiUrlData = @@ -135,14 +180,26 @@ class _PolicyListState extends State { handleActiveStatus(policydata, policyId.toString(), status.toString()); } - // Future deleteGroupFromApi(int groupId) async { - // try { - // await apiService.deleteGroup(groupId); // your delete API call - // deleteGroup(groupId); // remove from UI list - // } catch (e) { - // print('Error deleting group: $e'); - // } - // }' + Future loadAllGroups() async { + try { + final result = await apiService.fetchAllPolicy(); + + // Sort by policy_id descending (latest first) + result.sort((a, b) { + int idA = int.tryParse(a['policy_id'].toString()) ?? 0; + int idB = int.tryParse(b['policy_id'].toString()) ?? 0; + return idB.compareTo(idA); // latest first + }); + + setState(() { + futurePolicy = result as Future; + }); + print("Fetched services: $futurePolicy"); + } catch (e) { + print('Error fetching role list: $e'); + } + } + @override Widget build(BuildContext context) { @@ -153,23 +210,26 @@ class _PolicyListState extends State { return Scaffold( backgroundColor: Color(0xFFf5f5f5), + // appBar: isDesktop ? null : const CustomAppBar(title: 'User Management'), + // drawer: isDesktop ? null : CustomDrawer(isDesktop: false), appBar: CustomAppBar(isDesktop: isDesktop), drawer: CustomDrawer(isDesktop: false), body: Padding( padding: - isDesktop - ? EdgeInsets.symmetric( - horizontal: - MediaQuery.of(context).size.width * - 0.1, // 30% of screen width as horizontal padding - vertical: - MediaQuery.of(context).size.height * - 0, // 5% of screen height as vertical padding - ) - : EdgeInsets.all(0), + isDesktop + ? EdgeInsets.symmetric( + horizontal: + MediaQuery.of(context).size.width * + 0.1, // 30% of screen width as horizontal padding + vertical: + MediaQuery.of(context).size.height * + 0, // 5% of screen height as vertical padding + ) + : EdgeInsets.all(0), child: Row( children: [ // if (isDesktop) CustomDrawer(isDesktop: true), + // const Expanded(child: Center(child: Text("User Page Content"))), Expanded(child: buildGroupList(isDesktop)), ], ), @@ -182,247 +242,713 @@ class _PolicyListState extends State { Widget buildGroupList(bool isDesktop) { return Container( margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null, - padding: const EdgeInsets.only(left: 10, right: 10, top: 8), + padding: const EdgeInsets.all(1), decoration: BoxDecoration( color: isDesktop ? Colors.white : Color(0xFFFCFCFC), ), // decoration: BoxDecoration( // // color: Colors.amber, - // color: Color(0xFFE1F5FE), // // color: bodyColor, + // color: Color(0xFFE1F5FE), // border: Border.all( - // // color: Color(0xFFF7F7FB), // color: Colors.white, + // // color: Color(0xFFF7F7FB), // width: 3.5)), - child: buildGroupListLayout(isDesktop), + child: buildUserTable(isDesktop), ); } - Widget buildGroupListLayout(bool isDesktop) { + Widget buildUserTable(bool isDesktop) { return Container( // margin: isDesktop // ? EdgeInsets.all(10.0) // : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0), // padding: const EdgeInsets.all(10), height: - isDesktop - ? MediaQuery.of(context).size.height * 0.98 - : MediaQuery.of(context).size.height, - // decoration: BoxDecoration( - // border: isDesktop - // ? Border.all( - // width: 2, - // color: Colors.white, - // // color: Color(0xFFF7F7FB), - // ) - // : null, - // color: Colors.white, - // // color: Color(0xFFF7F7FB), - // - // // color: Colors.amber, - // ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + isDesktop + ? MediaQuery.of(context).size.height * 0.98 + : MediaQuery.of(context).size.height, + + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Container( + color: Colors.white, + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + // Divider( + // thickness: 0.2, // how "thick" the line is + // color: Colors.grey, // optional + // ), Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - 'Policy List', - style: GoogleFonts.poppins( - fontSize: isDesktop ? 16 : 14, - fontWeight: FontWeight.w600, - color: Colors.black, - ), + Row( + children: [ + Text( + 'Policy', + style: GoogleFonts.poppins( + fontSize: isDesktop ? 16 : 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + ], ), - IconButton( - icon: const Icon(Icons.keyboard_arrow_down), - onPressed: () {}, + if (isDesktop) + SizedBox(width: MediaQuery.of(context).size.width * 0.28), + + if (isDesktop) + Container( + width: MediaQuery.of(context).size.width * 0.2, + height: 40, + child: TextField( + controller: searchController, + onChanged: filterPolicy, + decoration: InputDecoration( + hintText: "Search for a Policy", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), + style: GoogleFonts.poppins(fontSize: 12), + ), + ), + // SizedBox(width: 16), + Spacer(), + + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF114D8B), + foregroundColor: Colors.white, + disabledBackgroundColor: Color(0xFF114D8B), + disabledForegroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: Color(0xFF114D8B), width: 2), + ), + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + ), + onPressed: () async { + List policyData = await futurePolicy; + + // Print the resolved value + print("CREATELIAS - $policyData"); + context.go('/Policy'); + + }, + child: Row( + mainAxisSize: + MainAxisSize.min, // Ensures content fits nicely + children: [ + Text( + "Add New Policy", + style: GoogleFonts.poppins( + fontSize: isDesktop ? 13 : 11, + ), + ), + SizedBox(width: 8), // spacing between icon and text + Icon( + Icons.add_circle_outline_rounded, + size: 15, + color: Colors.white, + ), + ], + ), ), ], ), - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Color(0xFF114D8B), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - // side: BorderSide(color: , width: 1), - ), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), - ), - onPressed: () async { - // List users = await futureUsers; - context.go('/Policy'); - }, - child: Row( - children: [ - Text( - 'New Policy', + + if (!isDesktop) SizedBox(height: 5), + isDesktop + ? SizedBox.shrink() + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.8, + height: 35, + child: TextField( + controller: searchController, + onChanged: filterPolicy, + decoration: InputDecoration( + hintText: "Search for a Policy", + hintStyle: TextStyle( + fontSize: 12, + color: Color(0xFF9E9DBD), + ), + prefixIcon: Icon( + Icons.search, + color: Color(0xFF9E9DBD), + size: 18, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade200, + width: 0.5, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 1, + ), + ), + ), style: GoogleFonts.poppins(fontSize: 12), ), - SizedBox(width: 5), - Icon(Icons.add_circle_outline_rounded, color: Colors.white), - ], - ), - ), - ], - ), - SizedBox(height: 5), - Row( - children: [ - Expanded( - child: Container( - height: MediaQuery.of(context).size.height * 0.8, - padding: const EdgeInsets.all(10), - // margin: const EdgeInsets.only(bottom: 10), - color: Colors.white, - // color: Colors.red.shade100, - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column(children: [buildGroupListView(isDesktop)]), ), - ), + // SizedBox(width: 16), + ], + ), + const SizedBox(height: 10), + FutureBuilder>( + future: futurePolicy, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError || + !snapshot.hasData || + snapshot.data!.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 8), + Text( + "No Policy Found", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.grey, + ), + ), + const SizedBox(height: 20), + Text( + "Please Create Policy", + textAlign: TextAlign.center, + style: GoogleFonts.poppins( + fontSize: 16, + color: Colors.grey, + ), + ), + const SizedBox(height: 20), + ], + ), + ), + ); + } + + List policyData = + filteredPolicy.isNotEmpty ? filteredPolicy : allPolicy; + + policyData.sort((a, b) { + DateTime dateA = DateTime.parse(a['created_on']); + DateTime dateB = DateTime.parse(b['created_on']); + + return dateB.compareTo(dateA); // Descending: newest first + }); + + List paginatedUser = + policyData + .skip(currentPage * itemsPerPage) + .take(itemsPerPage) + .toList(); + + Widget table = LayoutBuilder( + builder: (context, constraints) { + double minWidth = isDesktop ? constraints.maxWidth : 1300; + + return ConstrainedBox( + constraints: BoxConstraints(minWidth: minWidth), + child: DataTable( + dividerThickness: 0.5, + columnSpacing: isDesktop ? 24.0 : 16.0, + border: TableBorder( + horizontalInside: BorderSide( + width: 0.5, + color: Colors.grey.shade200, + ), + ), + columns: [ + DataColumn( + label: Text( + 'Policy Name', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Policy Type', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Status', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + DataColumn( + label: Text( + 'Actions', + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + rows: + paginatedUser.map((policy) { + String policyId = + policy['policy_id'].toString(); // Get policy ID + bool isSelected = selectedPolicyId == policyId; + + return DataRow( + cells: [ + DataCell( + Text( + "${policy['name'] ?? ''}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + policy['domestic'] == "1" + ? "Domestic" + : "International", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + ), + ), + ), + DataCell( + Text( + policy['is_active'] == "1" + ? "Active" + : "Inactive", + style: TextStyle( + color: + policy['is_active'] == "1" + ? Colors.green + : Colors.grey, + fontFamily: "Inter", + fontWeight: FontWeight.w400, + ), + ), + ), + DataCell( + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + GestureDetector( + onTap: () async { + final rawId = policy['policy_id']; + final intPolicyId = + rawId is int + ? rawId + : int.tryParse(rawId.toString()) ?? 0; + + Map policyData = await apiService + .getSinglePolicy(intPolicyId); + + print("PolicyDATa: $policyData"); + + context.go("/Policy", extra: policyData); + }, + child: Tooltip( + message: 'Edit Policy Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + ), + SizedBox(width: 5), + GestureDetector( + onTap: () { + final idStr = policy['policy_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("group_id is null"); + return; + } + final status = policy['is_active']; + + deletePolicy(policy, id, status); + }, + child: Tooltip( + message: 'Delete Policy Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + ), + ),), + ], + ), + ), + ], + ); + }).toList(), + ), + ); + }, + ); + Widget buildMobileCardView(List paginatedUser) { + return ListView.builder( + itemCount: paginatedUser.length, + itemBuilder: (context, index) { + final object = paginatedUser[index]; + + return Card( + color: Colors.white, + margin: EdgeInsets.symmetric(horizontal: 12, vertical: 6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 3, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Row 1: Policy Name and Actions + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.black, + ), + children: [ + TextSpan( + text: "Policy Name: ", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + TextSpan( + text: "${object['name'] ?? 'N/A'}", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + fontWeight: FontWeight.normal + ), + ), + ], + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () async { + final rawId = object['policy_id']; + final intPolicyId = rawId is int + ? rawId + : int.tryParse(rawId.toString()) ?? 0; + + Map policyData = + await apiService.getSinglePolicy(intPolicyId); + + print("PolicyDATa: $policyData"); + + context.go("/Policy", extra: policyData); + }, + child: Tooltip( + message: 'Edit Policy Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ), + ), + ), + SizedBox(width: 5), + GestureDetector( + onTap: () { + final idStr = object['policy_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("policy_id is null"); + return; + } + final status = object['is_active']; + + deletePolicy(object, id, status); + }, + child: Tooltip( + message: 'Delete Policy Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + ), + ), + ), + ], + ), + ], + ), + + SizedBox(height: 8), // Spacing + + // Row 2: Policy Type + RichText( + text: TextSpan( + style: GoogleFonts.poppins( + fontSize: 13, + color: Colors.black, + ), + children: [ + TextSpan( + text: "Policy Type: ", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + TextSpan( + text: object['domestic'] == "1" + ? "Domestic" + : "International", + style: TextStyle( + fontSize: 13, + fontFamily: "Inter", + fontWeight: FontWeight.normal + ), + ), + ], + ), + ), + ], + ), + ), + ); + }, + ); + } + + + Widget buildMobileCardView2(List paginatedUser) { + return ListView.builder( + itemCount: paginatedUser.length, + itemBuilder: (context, index) { + final object = paginatedUser[index]; + return Card( + color: Colors.white, + margin: EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 3, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + + Expanded( + flex: 1, + child: Text( + "Policy Type", + style: GoogleFonts.poppins( + fontSize: 11.5, + fontWeight: FontWeight.w400, + ), + ), + ), + // Expanded(flex: 1, child: Text("${policy['created_by']}")), + ], + ), + SizedBox(height: 4), + Column( + children: [ + Expanded( + flex: 1, + child: Text( + "${object['name']}", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + Expanded( + flex: 1, + child: Text( + object['domestic'] == "1" + ? "Domestic" + : "International", + style: GoogleFonts.poppins( + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + // Expanded(flex: 1, child: Text("${policy['created_by']}")), + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () async { + final rawId = object['policy_id']; + final intPolicyId = + rawId is int + ? rawId + : int.tryParse(rawId.toString()) ?? 0; + + Map policyData = await apiService + .getSinglePolicy(intPolicyId); + + print("PolicyDATa: $policyData"); + + context.go("/Policy", extra: policyData); + }, + child: Tooltip( + message: 'Edit Policy Details', + child: Image.asset( + 'assets/images/IconsImg/edit.png', + width: 20, + height: 15, + ),), + ), + SizedBox(width: 5), + GestureDetector( + onTap: () { + final idStr = object['policy_id']; + final id = int.tryParse(idStr.toString()); + + if (id == null) { + print("group_id is null"); + return; + } + final status = object['is_active']; + + deletePolicy(object, id, status); + }, + child: Tooltip( + message: 'Delete Policy Details', + child: Image.asset( + 'assets/images/IconsImg/delete.png', + width: 20, + height: 15, + ),), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } + + return Expanded( + child: Column( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: + isDesktop + ? SingleChildScrollView( + scrollDirection: Axis.vertical, + child: table, // <-- your existing table + ) + : buildMobileCardView(paginatedUser), + ), + PaginationControls( + currentPage: currentPage, + itemsPerPage: itemsPerPage, + totalItems: policyData.length, + activeColor: layoutColor, // your theme color + onPageChanged: (page) { + setState(() { + currentPage = page; + }); + }, + onItemsPerPageChanged: (items) { + setState(() { + itemsPerPage = items; + currentPage = 0; + }); + }, + ), + ], + ), + ); + }, ), ], ), - ], + ), ), ); } - - // Widget buildGroupListView(bool isDesktop) { - // return Container( - // child: Text("DAta"), - // ); - // } - - Widget buildGroupListView(bool isDesktop) { - if (apiAllGroups == null || apiAllGroups!.isEmpty) { - return Center(child: Text("No Policy Found.")); - } - - return ListView.builder( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: apiAllGroups!.length, - itemBuilder: (context, index) { - final policy = apiAllGroups![index]; - return Card( - // color: bodyColor, - // color: Color(0xFFF5F5F5), - color: Colors.white, - margin: EdgeInsets.symmetric(vertical: 6, horizontal: 10), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - flex: 1, - child: Text( - "Policy Name", - style: GoogleFonts.poppins( - fontSize: 11.5, - fontWeight: FontWeight.w400, - ), - ), - ), - Expanded( - flex: 1, - child: Text( - "Policy Type", - style: GoogleFonts.poppins( - fontSize: 11.5, - fontWeight: FontWeight.w400, - ), - ), - ), - // Expanded(flex: 1, child: Text("${policy['created_by']}")), - ], - ), - SizedBox(height: 4), - Row( - children: [ - Expanded( - flex: 1, - child: Text( - "${policy['name']}", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - Expanded( - flex: 1, - child: Text( - policy['domestic'] == "1" - ? "Domestic" - : "International", - style: GoogleFonts.poppins( - fontSize: 13, - fontWeight: FontWeight.w600, - ), - ), - ), - // Expanded(flex: 1, child: Text("${policy['created_by']}")), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - GestureDetector( - onTap: () async { - final rawId = policy['policy_id']; - final intPolicyId = - rawId is int - ? rawId - : int.tryParse(rawId.toString()) ?? 0; - - Map policyData = await apiService - .getSinglePolicy(intPolicyId); - - print("PolicyDATa: $policyData"); - - context.go("/Policy", extra: policyData); - }, - child: Image.asset( - 'assets/images/IconsImg/edit.png', - width: 20, - height: 15, - ), - ), - SizedBox(width: 5), - GestureDetector( - onTap: () { - final idStr = policy['policy_id']; - final id = int.tryParse(idStr.toString()); - - if (id == null) { - print("group_id is null"); - return; - } - final status = policy['is_active']; - - deletePolicy(policy, id, status); - }, - child: Image.asset( - 'assets/images/IconsImg/delete.png', - width: 20, - height: 15, - ), - ), - ], - ), - ], - ), - ), - ); - }, - ); - } -} +} \ No newline at end of file diff --git a/lib/Screens/traveller/travellerList.dart b/lib/Screens/traveller/travellerList.dart index 1076c5a..7cb3ecd 100644 --- a/lib/Screens/traveller/travellerList.dart +++ b/lib/Screens/traveller/travellerList.dart @@ -153,6 +153,7 @@ class TravellerListState extends State { false) || (isActiveStatus.contains(lowerQuery)); }).toList(); + currentPage = 0; }); print("filteredTraveller: $filteredTraveller"); }