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:intl/intl.dart'; import 'package:nhance_partner/data/utils/toastNotification.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../../core/responsive/responsive_builder.dart'; import '../../../../core/routing/routes.dart'; import '../../../../core/services/api_service.dart'; import '../../../providers/manager_provider.dart'; import '../../../providers/quotation_staff_proivder.dart'; import '../../../providers/userRoleProvider.dart'; import '../../staff/Enquiry/tabs/tab.dart'; import '../../staff/assignStaff.dart'; class PartnerDashboard extends ConsumerStatefulWidget { const PartnerDashboard({super.key}); @override ConsumerState createState() => _PartnerDashboardState(); } class _PartnerDashboardState extends ConsumerState { /// ✅ DATE STATE (ONLY FOR PARTNER TAB) DateTime? fromDate; DateTime? toDate; int selectedIndex = 1; int switcherStatus = 1; late ApiService apiService; String? policiesIssuedToday; String? policiesIssuedYear; String? policiesIssuedMonth; String? premiumValueToday; String? premiumValueYear; String? premiumValueMonth; String? earningsToday; String? earningsMonth; String? earningsYear; String? quotationsPendingCounts; // cross verify String? currentKey; // cross verify String? SelctdPartnerbroker; // cross verify // List> dataVal = []; List> getStaffData = []; // List> originalData = []; // List> filteredData = []; int selectedTabIndex = 0; List> currentList = []; List> staffQuotationsPendingList = []; // cross verify List> quotationsPendingList = []; // cross verify List> policiesPendingList = []; // cross verify List> awaitingApprovalList = []; // cross verify List> unAssignedEnqList = []; // cross verify List> agentsPerformanceList = []; // cross verify List> nonAgentsPerformanceList = []; List> agentsPerformanceListPremium = []; // cross verify List> nonAgentsPerformanceListPremium = []; // cross verify dynamic prefid; dynamic prefroleId; bool isLoading = false; List> getBusinessDshBdData = []; List> originalData = []; List> filteredData = []; List> brokerWise = []; List> productWise = []; List> insurerWise = []; List> originalBrokerWise = []; List> filteredBrokerWise = []; List> originalProductWise = []; List> filteredProductWise = []; List> originalInsurerWise = []; List> filteredInsurerWise = []; bool isPerfomingAgntPolicy = true; bool isNonPerfomingAgntPolicy = true; bool isBrokerWisePolicy = true; bool isProductWisePolicy = true; @override void initState() { super.initState(); apiService = ApiService(); Future.microtask(() { final prefmanagerid = ref.read(managerIdProvider); final prefuserid = ref.read(userIdProvider); final prefroleId = ref.read(userRoleProvider); print("B81 => roleId: $prefroleId | userId: $prefuserid "); if (prefmanagerid != null) { getParnterDashBrdList(prefmanagerid); // getStaffList(prefmanagerid!, prefroleId, prefuserid); } }); } void refresh() { print('___DASHBOARD___'); final prefmanagerid = ref.read(managerIdProvider); final prefuserid = ref.read(userIdProvider); final prefroleId = ref.read(userRoleProvider); // if (prefuserid != null) { // print("REFRESH- calling getStaffList with $prefmanagerid, $prefuserid"); // getStaffList(prefmanagerid!, prefroleId, prefuserid); // } } /// 🔹 DATE PICKER Future pickDate(bool isFrom) async { final picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2022), lastDate: DateTime.now(), ); if (picked != null) { setState(() { if (isFrom) { fromDate = picked; } else { toDate = picked; } }); // OPTIONAL: reload API with date range // final managerId = ref.read(managerIdProvider); // if (managerId != null) { // getParnterDashBrdList(managerId); // } } } /// 🔹 DATE PICKER UI Widget headerDatePicker({ required String label, DateTime? date, required VoidCallback onTap, }) { return InkWell( onTap: onTap, child: Container( height: 32, padding: const EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all(color: Colors.grey.shade300), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.calendar_today, size: 14, color: Colors.grey), const SizedBox(width: 6), Text( date == null ? label : DateFormat('dd-MM-yyyy').format(date), style: GoogleFonts.inter(fontSize: 11), ), ], ), ), ); } Future getParnterDashBrdList(id) async { // print('getClaimList called MagId - $managerId - $role'); setState(() { isLoading = true; }); // dynamic id = widget.policyNumber; print('getBusinessDshID - $id - $fromDate - $toDate'); try { final response = await apiService.findPartnerDashboardData(id,fromDate,toDate); if (response['status'] == 'success') { final data = response['data']; print('getBusinessDshBdData - ${response['data']}'); setState(() { if (data is List) { // Already a list of maps getBusinessDshBdData = List>.from(data); } else if (data is Map) { // Single object, wrap in a list getBusinessDshBdData = [Map.from(data)]; } else { getBusinessDshBdData = []; } // getBusinessDshBdData = List>.from(response['data']); originalData = getBusinessDshBdData; filteredData = List.from(originalData); // print('originalData - $getClaimPolicies'); }); if (data is Map) { setState(() { // agents_performance Policy if (data['agentsPerformanceList'] != null) { agentsPerformanceList = List>.from( (data['agentsPerformanceList'] as List).map( (item) => Map.from(item), ), ); } // agents_performance Premium if (data['monthlyPremiumAmount'] != null) { agentsPerformanceListPremium = List>.from( (data['monthlyPremiumAmount'] as List).map( (item) => Map.from(item), ), ); } if (data['nonAgentsPerformanceList'] != null) { nonAgentsPerformanceList = List>.from( (data['nonAgentsPerformanceList'] as List).map( (item) => Map.from(item), ), ); } // agents_performance Premium if (data['nonAgentsPerformanceListPremium'] != null) { nonAgentsPerformanceListPremium = List>.from( (data['nonAgentsPerformanceListPremium'] as List).map( (item) => Map.from(item), ), ); } print( 'agentsPerformanceListPremium - ${agentsPerformanceListPremium}', ); originalBrokerWise = List.from(brokerWise); filteredBrokerWise = List.from(brokerWise); // Store ProductWise productWise = List>.from( data['productWise'] ?? [], ); print('productWise - ${productWise}'); originalProductWise = List.from(productWise); filteredProductWise = List.from(productWise); // Store InsurerWise insurerWise = List>.from( data['insurerWise'] ?? [], ); print('insurerWise - ${insurerWise}'); originalInsurerWise = List.from(insurerWise); filteredInsurerWise = List.from(insurerWise); }); } else { // fallback brokerWise = []; productWise = []; insurerWise = []; } } else { getBusinessDshBdData = []; originalData = []; } } catch (e) { print('Exception occurred: $e'); } finally { setState(() { isLoading = false; }); } } Future handleEdit(String id) async { // Navigator.pop(context); print('EDITStaff'); print('EDITStaff - $id'); // dynamic id = data['id']; // context.go('/tabEnquiry/$id'); final prefs = await SharedPreferences.getInstance(); // ✅ Remove old value (if any) await prefs.remove('enqAgentDataId'); // setState(() { // final id = item['id'].toString(); // ✅ Save the new id // await prefs.setString('enqAgentDataId', id.toString()); await prefs.setString('enqAgentDataId', id); ref.read(enquiryIdProvider.notifier).state = id; context.go(AppRoutes.tabEnquiry); } Future handleStaffEdit(String id, String? flag) async { // Navigator.pop(context); ddd dynamic val; print('EDITStaff - $id'); if (flag == "Policies") { val = 'Policy'; } else { val = ''; } var enqId = id; final prefs = await SharedPreferences.getInstance(); // ✅ Remove old value (if any) await prefs.remove('enqStaffDataId'); // ✅ Save the new id await prefs.setString('enqStaffDataId', enqId.toString()); await prefs.setString('navFromDashboard', 'Dashboard'); ref.read(quotationStaffIdProvider.notifier).state = enqId; ref.read(navFromEnqStaffProvider.notifier).state = 'Dashboard'; // showDialog( // context: context, // builder: (context) => TabEnquiryStaffList(showKey: val), // ); final result = await showDialog( context: context, barrierDismissible: false, // optional - prevents closing by tapping outside builder: (context) => TabEnquiryStaffList(showKey: val), ); // ✅ Code here runs *after* the dialog is closed print("Dialog closed"); print("Dialog result: $result"); refresh(); } void onSearch() { final managerId = ref.read(managerIdProvider); if (managerId == null) return; // Print to verify state before calling API print("Search Triggered: $fromDate to $toDate"); // OPTIONAL: validation if (fromDate != null && toDate != null && fromDate!.isAfter(toDate!)) { ToastHelper.showWarningToast(context, 'From date cannot be after To date'); // ScaffoldMessenger.of(context).showSnackBar( // const SnackBar(content: Text('From date cannot be after To date')), // ); return; } // 🔍 Call API with date filter getParnterDashBrdList(managerId); } void onReset() { setState(() { fromDate = null; toDate = null; }); final managerId = ref.read(managerIdProvider); if (managerId != null) { // ♻️ Reload without date filter getParnterDashBrdList(managerId); } } @override Widget build(BuildContext context) { // final enquiries = ref.watch(enquiriesProvider); final managerId = ref.watch(managerIdProvider); final userId = ref.watch(userIdProvider); final role = ref.watch(userRoleProvider); return SelectionArea( child: Column( children: [ Container( margin: EdgeInsets.all(0), // color: Colors.red.shade100, // height: MediaQuery.of(context).size.height * 0.75, child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( children: [ const Spacer(), headerDatePicker( label: 'From', date: fromDate, onTap: () => pickDate(true), ), const SizedBox(width: 8), headerDatePicker( label: 'To', date: toDate, onTap: () => pickDate(false), ), const SizedBox(width: 8), /// ♻️ RESET actionIcon( icon: Icons.refresh, tooltip: 'Reset', onTap: onReset, ), const SizedBox(width: 6), /// 🔍 SEARCH actionIcon( icon: Icons.search, tooltip: 'Search', onTap: onSearch, ), ], ), ), if (role == 'manager' || role == 'handler' || role == 'agent') SizedBox( height: MediaQuery.of(context).size.height * 0.78, // ✅ replace Expanded // height: 350, // adjust height as needed child: Row( children: [ Expanded( child: Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 4, offset: Offset(0, 2), ), ], ), child: Column( children: [ Padding( padding: const EdgeInsets.only( top: 8.0, bottom: 16.0, ), child: Row( children: [ Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Performing Partner ( Top 50 )', style: _chartHeader, ), SizedBox(width: 10), InkWell( onTap: () async { final path = "PerformingTop50"; final id = ''; final month = 'current'; await apiService .generateChartExcel( path, id, month, managerId, fromDate: fromDate, toDate: toDate, ); }, child: Tooltip( message: 'Export Excel', child: Container( padding: const EdgeInsets.all( 5.0, ), decoration: BoxDecoration( color: const Color( 0xFF2E7D6E, ), // color: const Color(0xFF425B5B), borderRadius: BorderRadius.circular( 2.0, ), ), child: Image.asset( "assets/miscellaneous/export.png", height: 11, width: 11, // color: Colors.green, ), ), ), ), ], ), ), // Text( // isPerfomingAgntPolicy // ? "Policies" // : "Premium", // style: _styleSmall1, // ), // // Transform.scale( // scale: 0.5, // child: Switch( // value: isPerfomingAgntPolicy, // activeColor: Colors.teal, // activeTrackColor: Colors.grey.shade200, // inactiveThumbColor: Colors.orange, // inactiveTrackColor: Colors.white, // onChanged: (val) { // setState( // () => isPerfomingAgntPolicy = val, // ); // }, // ), // ), ], ), ), Expanded( child: Performance( title: "Performing Partner", data: isPerfomingAgntPolicy ? agentsPerformanceList : agentsPerformanceListPremium, isPerfomingAgntPolicy: isPerfomingAgntPolicy, apiService: apiService, managerId: managerId, fromDate: fromDate, toDate: toDate, ), ), ], ), ), ), SizedBox(width: 16), Expanded( child: Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 4, offset: Offset(0, 2), ), ], ), child: Column( children: [ Row( children: [ Expanded( child: Text( 'Non Performing Partner', style: _chartHeader, ), ), SizedBox(width: 10), Text( isNonPerfomingAgntPolicy ? "No Business" : "Business Less than 50,000", style: _styleSmall1, ), Transform.scale( scale: 0.5, child: Switch( value: isNonPerfomingAgntPolicy, activeColor: Colors.teal, activeTrackColor: Colors.grey.shade200, inactiveThumbColor: Colors.orange, inactiveTrackColor: Colors.white, onChanged: (val) { setState( () => isNonPerfomingAgntPolicy = val, ); }, ), ), SizedBox(width: 5), InkWell( onTap: () async { final path = isNonPerfomingAgntPolicy ? "NoBusiness" : "NonPerformingBelow50K"; final id = ''; final month = 'current'; await apiService.generateChartExcel( path, id, month, managerId, fromDate: fromDate, toDate: toDate, ); }, child: Tooltip( message: 'Export Excel', child: Container( padding: const EdgeInsets.all(5.0), decoration: BoxDecoration( color: const Color(0xFF2E7D6E), // color: const Color(0xFF425B5B), borderRadius: BorderRadius.circular( 2.0, ), ), child: Image.asset( "assets/miscellaneous/export.png", height: 11, width: 11, // color: Colors.green, ), ), ), ), ], ), Expanded( child: Performance( title: "Non-Performing Partner", data: isNonPerfomingAgntPolicy ? nonAgentsPerformanceList : nonAgentsPerformanceListPremium, isPerfomingAgntPolicy: isNonPerfomingAgntPolicy, apiService: apiService, managerId: managerId, fromDate: fromDate, toDate: toDate, ), ), ], ), ), ), ], ), ), ], ), ), ), ], ) ); } Widget actionIcon({ required IconData icon, required String tooltip, required VoidCallback onTap, }) { return Tooltip( message: tooltip, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(6), child: Container( height: 32, width: 32, decoration: BoxDecoration( color: const Color(0xFF2E7D6E), borderRadius: BorderRadius.circular(6), ), child: Icon(icon, size: 16, color: Colors.white), ), ), ); } } class Performance extends StatefulWidget { final String title; final List> data; final bool isPerfomingAgntPolicy; late ApiService apiService; dynamic managerId; final DateTime? fromDate; final DateTime? toDate; Performance({ Key? key, required this.title, required this.data, required this.isPerfomingAgntPolicy, required this.apiService, required this.managerId, this.fromDate, this.toDate, }) : super(key: key); @override State createState() => _PerformanceState(); } class _PerformanceState extends State { late bool isPerfomingAgntPolicy; @override void initState() { super.initState(); isPerfomingAgntPolicy = widget.isPerfomingAgntPolicy; } @override Widget build(BuildContext context) { return Container( color: Colors.white, // elevation: 1, // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(0.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // HEADER Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), decoration: BoxDecoration( color: Color(0xFFE3F9F8), borderRadius: BorderRadius.circular(10), ), child: Row( children: [ Expanded( flex: 1, child: Text( "S.No.", textAlign: TextAlign.left, style: _headerStyle, ), ), Expanded( flex: 1, child: Text( "Partner Code", textAlign: TextAlign.left, style: _headerStyle, ), ), Expanded( flex: 2, child: Text( "Partner Name", textAlign: TextAlign.left, style: _headerStyle, ), ), if (widget.title == 'Performing Partner') ...[ Expanded( flex: 1, child: Text( "Policy Count", textAlign: TextAlign.center, style: _headerStyle, ), ), Expanded( flex: 1, child: Text( "Premium Amount", textAlign: TextAlign.center, style: _headerStyle, ), ), ], ], ), ), const SizedBox(height: 8), // LIST Flexible( child: ListView.builder( itemCount: widget.data.length, itemBuilder: (context, index) { final row = widget.data[index]; return Container( margin: const EdgeInsets.symmetric(vertical: 5), padding: const EdgeInsets.symmetric( vertical: 5, horizontal: 12, ), decoration: BoxDecoration( color: Colors.white, border: Border( bottom: BorderSide( color: Colors.blueGrey.shade100, width: 0.3, ), ), ), child: Row( children: [ Expanded( flex: 1, child: Text( (index + 1).toString(), textAlign: TextAlign.left, style: _tableDataStyle, ), ), Expanded( flex: 1, child: Text( row['agent_code'] ?? "", textAlign: TextAlign.left, style: _tableDataStyle, ), ), Expanded( flex: 2, child: Text( row['agent_name'] ?? "", textAlign: TextAlign.left, style: _tableDataStyle, ), ), if (widget.title == 'Performing Partner') ...[ Expanded( flex: 1, child: Text( row['policy_count'] ?? "", textAlign: TextAlign.center, style: _tableDataStyle, ), ), Expanded( flex: 1, child: Text( row['total_premium_amount'] ?? "", textAlign: TextAlign.right, style: _tableDataStyle, ), ), ], SizedBox(width: 10), if (widget.title == 'Performing Partner') ...[ InkWell( onTap: () async { final path1 = 'PerformingAgentsByID'; final path2 = widget.isPerfomingAgntPolicy ? "NoBusiness" : "NonPerformingBelow50K"; final path = (widget.title == 'Performing Partner') ? path1 : path2; final id = ((widget.title == 'Performing Partner') && (row['agent_id'] != null)) ? row['agent_id'] : ''; final month = 'current'; await widget.apiService.generateChartExcel( path, id, month, widget.managerId, fromDate: widget.fromDate, toDate: widget.toDate, // widget.fromDate,widget.toDate ); }, child: Tooltip( message: 'Click To Download Excel', child: Icon( Icons.download, size: 14, color: Colors.green.shade300, ), ), ), ], ], ), ); }, ), ), ], ), ), ); } } class UnassignedEnq extends StatelessWidget { final String title; final List> data; final VoidCallback? onRefresh; String role; UnassignedEnq({ Key? key, required this.title, required this.data, this.onRefresh, required this.role, }) : super(key: key); @override Widget build(BuildContext context) { return Card( color: Colors.white, // color: const Color(0xFFEAF6F4), elevation: 1, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title Text(title, style: _title), const SizedBox(height: 10), // Header row Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), decoration: BoxDecoration( // color: const Color(0xFF3E5B56), color: Color(0xFFE3F9F8), borderRadius: BorderRadius.circular(10), ), child: Row( children: [ // Expanded( // child: Text( // "S.No", // textAlign: TextAlign.center, // style: _headerStyle, // ), // ), Expanded( child: Text( "Date", // textAlign: TextAlign.center, style: _headerStyle, ), ), Expanded( child: Text( "Partner", // textAlign: TextAlign.center, style: _headerStyle, ), ), Expanded( child: Text( "Reg.No.", // textAlign: TextAlign.center, style: _headerStyle, ), ), Expanded( child: Text( "Insured Name", // textAlign: TextAlign.center, style: _headerStyle, ), ), ], ), ), const SizedBox(height: 8), // List of rows Flexible( child: ListView.builder( itemCount: data.length, itemBuilder: (context, index) { final row = data[index]; String date = ""; String time = ""; if ((row['created_on'] ?? "").isNotEmpty) { final parts = row['created_on'].split(' '); date = parts[0]; if (parts.isNotEmpty) { DateTime parsedDate = DateTime.parse(parts[0]); date = DateFormat( 'dd-MM-yyyy', ).format(parsedDate); // 19/09/2025 } // time = parts.length > 1 ? parts[1] : ""; // Format the time part (HH:mm) if (parts.length >= 2) { final timeParts = parts[1].split(":"); time = "${timeParts[0]}:${timeParts[1]}"; // 05:45 } else { time = ""; } } return InkWell( focusColor: Color(0xFF3E5B56), highlightColor: Color(0xFF3E5B56), borderRadius: BorderRadius.circular(2), // for ripple effect // onTap: () { // handleDashboardNavigation( // context, // status: "To be assigned", // staffId: row['staff_id'] ?? '', // role: role, // ); // }, onTap: () { // Print the id when row is clicked print("Clicked ID fd: ${row['id']}"); // You can also navigate or perform any action here showDialog( context: context, builder: (ctx) => AssignStaffDialog( enquiryPrimaryId: row['id'], regNum: row['reg_no'], userId: 1, onSubmit: (value) { debugPrint("New assignY: $value"); if (onRefresh != null) { onRefresh!(); // ✅ call the parent's refresh } }, ), ); }, child: Container( // height: 5200, margin: const EdgeInsets.symmetric(vertical: 5), padding: const EdgeInsets.symmetric( vertical: 5, horizontal: 12, ), decoration: BoxDecoration( color: Colors.white, border: Border( bottom: BorderSide( color: Colors.blueGrey.shade100, width: 0.3, ), ), // borderRadius: BorderRadius.circular(10), ), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(date, style: _tableDataStyle), Text(time, style: _tableDataTimeStyle), ], ), ), Expanded( child: Text( row['agent_name'] ?? '', // convert int to string // textAlign: TextAlign.center, style: _tableDataStyle, ), ), Expanded( child: Text( row['reg_no'] ?? "", style: _tableDataStyle, ), ), Expanded( child: Text( row['insured_name'] ?? "", style: _tableDataStyle, ), ), ], ), ), ); }, ), ), ], ), ), ); } } Future handleDashboardNavigation( BuildContext context, { required String status, String? staffId, required String role, }) async { print('Dashboard Tap => Status: $status | Staff: $staffId'); final prefs = await SharedPreferences.getInstance(); // ✅ Clear any old data await prefs.remove('dashboardKeyProvider'); await prefs.remove('dashboardStatusProvider'); await prefs.remove('dashboardStaffIdProvider'); // ✅ Save new values await prefs.setString('dashboardKeyProvider', 'fromDashboard'); await prefs.setString('dashboardStatusProvider', status); await prefs.setString('dashboardStaffIdProvider', staffId!); context.go(AppRoutes.enquiryForStaff); // // ✅ Navigate // if (role == 'manager') { // context.go(AppRoutes.enquiryForStaff); // } else { // context.go(AppRoutes.enquiryHandlerLst); // } } final _headerStyle = GoogleFonts.inter( fontWeight: FontWeight.w600, fontSize: 11.5, color: Colors.black, ); final _title = GoogleFonts.inter( fontWeight: FontWeight.bold, fontSize: 11.5, // color: Colors.red, color: const Color(0xff425B5B), ); final _tableDataStyle = GoogleFonts.inter( fontSize: 11, fontWeight: FontWeight.w500, ); final _tableDataTimeStyle = GoogleFonts.inter( fontSize: 10, fontWeight: FontWeight.w400, ); final topHeaderStyle = GoogleFonts.inter( fontSize: 11, color: Colors.black, fontWeight: FontWeight.w500, ); final _styleSmall1 = GoogleFonts.poppins( fontSize: 10, fontWeight: FontWeight.w400, ); final _chartHeader = GoogleFonts.poppins( fontSize: 11.5, color: Colors.black, fontWeight: FontWeight.w500, );