1067 lines
34 KiB
Dart
1067 lines
34 KiB
Dart
import 'package:dropdown_search/dropdown_search.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/src/widgets/framework.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:nhance_partner/presentation/providers/manager_provider.dart';
|
|
|
|
import '../../../../core/services/api_service.dart';
|
|
import '../../../../data/models/bar_data.dart';
|
|
import '../../../providers/userRoleProvider.dart';
|
|
import '../../../themes/charts/barChart.dart';
|
|
import '../../../themes/charts/barChart_horizontal.dart';
|
|
import '../../../themes/indicators/input_field_decoration.dart';
|
|
|
|
class BussinessDashboard extends ConsumerStatefulWidget {
|
|
const BussinessDashboard({super.key});
|
|
|
|
@override
|
|
ConsumerState<BussinessDashboard> createState() => _BussinessDashboardState();
|
|
}
|
|
|
|
class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|
dynamic managerId;
|
|
late ApiService apiService;
|
|
|
|
String? selectedInsurer;
|
|
|
|
// List<Map<String, dynamic>> dataVal = [];
|
|
List<Map<String, dynamic>> getBusinessDshBdData = [];
|
|
List<Map<String, dynamic>> originalData = [];
|
|
List<Map<String, dynamic>> filteredData = [];
|
|
|
|
List<Map<String, dynamic>> brokerWise = [];
|
|
List<Map<String, dynamic>> productWise = [];
|
|
List<Map<String, dynamic>> insurerWise = [];
|
|
|
|
List<Map<String, dynamic>> originalBrokerWise = [];
|
|
List<Map<String, dynamic>> filteredBrokerWise = [];
|
|
|
|
List<Map<String, dynamic>> originalProductWise = [];
|
|
List<Map<String, dynamic>> filteredProductWise = [];
|
|
|
|
List<Map<String, dynamic>> originalInsurerWise = [];
|
|
List<Map<String, dynamic>> filteredInsurerWise = [];
|
|
|
|
List<Map<String, dynamic>> getInsuranceTypeData = [];
|
|
List<Map<String, dynamic>> filteredInsuranceData = [];
|
|
|
|
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
|
|
dropDownKeyInsurer = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
|
|
|
|
bool isLoading = false;
|
|
bool isInsureWisePolicy = true;
|
|
bool isBrokerWisePolicy = true;
|
|
bool isProductWisePolicy = true;
|
|
|
|
bool showInsurer = true;
|
|
bool showBroker = true;
|
|
bool showProduct = true;
|
|
|
|
int selectedView = 0;
|
|
// 0 = Insurer
|
|
// 1 = Broker
|
|
// 2 = Product
|
|
|
|
String? SelctdBusinessbroker;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
apiService = ApiService();
|
|
|
|
Future.microtask(() {
|
|
// final id = ref.read(managerIdProvider);
|
|
final roleId = ref.read(userRoleProvider);
|
|
managerId = ref.read(managerIdProvider);
|
|
|
|
// print("ENQroleId - $roleId");
|
|
|
|
if (managerId != null) {
|
|
getBusinessDashBrdList(managerId);
|
|
}
|
|
});
|
|
}
|
|
|
|
Future<void> getBusinessDashBrdList(id) async {
|
|
// print('getClaimList called MagId - $managerId - $role');
|
|
setState(() {
|
|
isLoading = true;
|
|
});
|
|
// dynamic id = widget.policyNumber;
|
|
print('getBusinessDshID - $id');
|
|
try {
|
|
final response = await apiService.findBusinessDashboardData(
|
|
id,
|
|
SelctdBusinessbroker,
|
|
);
|
|
|
|
if (response['status'] == 'success') {
|
|
final data = response['data'];
|
|
print('getBusinessDshBdData - ${response['data']}');
|
|
setState(() {
|
|
if (data is List) {
|
|
// Already a list of maps
|
|
getBusinessDshBdData = List<Map<String, dynamic>>.from(data);
|
|
} else if (data is Map) {
|
|
// Single object, wrap in a list
|
|
getBusinessDshBdData = [Map<String, dynamic>.from(data)];
|
|
} else {
|
|
getBusinessDshBdData = [];
|
|
}
|
|
// getBusinessDshBdData = List<Map<String, dynamic>>.from(response['data']);
|
|
originalData = getBusinessDshBdData;
|
|
filteredData = List.from(originalData);
|
|
// print('originalData - $getClaimPolicies');
|
|
});
|
|
|
|
if (data is Map<String, dynamic>) {
|
|
setState(() {
|
|
// Store BrokerWise
|
|
brokerWise = List<Map<String, dynamic>>.from(
|
|
data['brokerWise'] ?? [],
|
|
);
|
|
|
|
print('brokerWise - ${brokerWise}');
|
|
originalBrokerWise = List.from(brokerWise);
|
|
filteredBrokerWise = List.from(brokerWise);
|
|
|
|
// Store ProductWise
|
|
productWise = List<Map<String, dynamic>>.from(
|
|
data['productWise'] ?? [],
|
|
);
|
|
|
|
print('productWise - ${productWise}');
|
|
originalProductWise = List.from(productWise);
|
|
filteredProductWise = List.from(productWise);
|
|
|
|
// Store InsurerWise
|
|
insurerWise = List<Map<String, dynamic>>.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;
|
|
});
|
|
}
|
|
}
|
|
|
|
List<Map<String, dynamic>> getSortedInsurerWise() {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
final List<Map<String, dynamic>> sorted = List<Map<String, dynamic>>.from(
|
|
filteredInsurerWise,
|
|
);
|
|
|
|
sorted.sort((a, b) {
|
|
final aCurrent = isInsureWisePolicy
|
|
? parseDouble(a['total_policies_current_month'])
|
|
: parseDouble(a['total_premium_current_month']);
|
|
|
|
final aPrev = isInsureWisePolicy
|
|
? parseDouble(a['total_policies_pre_month'])
|
|
: parseDouble(a['total_premium_pre_month']);
|
|
|
|
final bCurrent = isInsureWisePolicy
|
|
? parseDouble(b['total_policies_current_month'])
|
|
: parseDouble(b['total_premium_current_month']);
|
|
|
|
final bPrev = isInsureWisePolicy
|
|
? parseDouble(b['total_policies_pre_month'])
|
|
: parseDouble(b['total_premium_pre_month']);
|
|
|
|
final aMax = aCurrent > aPrev ? aCurrent : aPrev;
|
|
final bMax = bCurrent > bPrev ? bCurrent : bPrev;
|
|
|
|
return bMax.compareTo(aMax); // DESC
|
|
});
|
|
|
|
return sorted;
|
|
}
|
|
|
|
List<BarData> buildInsurerBarData(List<Map<String, dynamic>> sortedList) {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
return sortedList.map((item) {
|
|
return BarData(
|
|
Colors.blue,
|
|
isInsureWisePolicy
|
|
? parseDouble(item['total_policies_current_month'])
|
|
: parseDouble(item['total_premium_current_month']),
|
|
isInsureWisePolicy
|
|
? parseDouble(item['total_policies_pre_month'])
|
|
: parseDouble(item['total_premium_pre_month']),
|
|
item['insurer_id'] ?? '0',
|
|
'Insurer',
|
|
5,
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
List<String> buildInsurerLabels(List<Map<String, dynamic>> sortedList) {
|
|
return sortedList.map<String>((item) {
|
|
final name = item['short_name'];
|
|
return (name != null && name.toString().trim().isNotEmpty)
|
|
? name.toString()
|
|
: '';
|
|
}).toList();
|
|
}
|
|
|
|
List<Map<String, dynamic>> getSortedBrokerWise() {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
final List<Map<String, dynamic>> sorted = List<Map<String, dynamic>>.from(
|
|
filteredBrokerWise,
|
|
);
|
|
|
|
sorted.sort((a, b) {
|
|
final aCurrent = isBrokerWisePolicy
|
|
? parseDouble(a['total_policies_current_month'])
|
|
: parseDouble(a['total_premium_current_month']);
|
|
|
|
final aPrev = isBrokerWisePolicy
|
|
? parseDouble(a['total_policies_pre_month'])
|
|
: parseDouble(a['total_premium_pre_month']);
|
|
|
|
final bCurrent = isBrokerWisePolicy
|
|
? parseDouble(b['total_policies_current_month'])
|
|
: parseDouble(b['total_premium_current_month']);
|
|
|
|
final bPrev = isBrokerWisePolicy
|
|
? parseDouble(b['total_policies_pre_month'])
|
|
: parseDouble(b['total_premium_pre_month']);
|
|
|
|
final aMax = aCurrent > aPrev ? aCurrent : aPrev;
|
|
final bMax = bCurrent > bPrev ? bCurrent : bPrev;
|
|
|
|
return bMax.compareTo(aMax); // 🔥 DESC
|
|
});
|
|
|
|
return sorted;
|
|
}
|
|
|
|
List<BarData> buildBrokerBarData(List<Map<String, dynamic>> sortedList) {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
return sortedList.map((item) {
|
|
return BarData(
|
|
Colors.blue,
|
|
isBrokerWisePolicy
|
|
? parseDouble(item['total_policies_current_month'])
|
|
: parseDouble(item['total_premium_current_month']),
|
|
isBrokerWisePolicy
|
|
? parseDouble(item['total_policies_pre_month'])
|
|
: parseDouble(item['total_premium_pre_month']),
|
|
item['broker_id'] ?? '0',
|
|
'Broker',
|
|
5,
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
List<String> buildBrokerLabels(List<Map<String, dynamic>> sortedList) {
|
|
return sortedList.map<String>((item) {
|
|
final name = item['broker_name'];
|
|
return (name != null && name.toString().trim().isNotEmpty)
|
|
? name.toString()
|
|
: '';
|
|
}).toList();
|
|
}
|
|
|
|
List<String> buildBrokerShortNames(List<Map<String, dynamic>> sortedList) {
|
|
return sortedList.map<String>((item) {
|
|
return item['broker_short_name']?.toString() ?? '';
|
|
}).toList();
|
|
}
|
|
|
|
List<Map<String, dynamic>> getSortedProductWise() {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
final List<Map<String, dynamic>> sorted = List<Map<String, dynamic>>.from(
|
|
filteredProductWise,
|
|
);
|
|
|
|
sorted.sort((a, b) {
|
|
final aCurrent = isProductWisePolicy
|
|
? parseDouble(a['total_policies_current_month'])
|
|
: parseDouble(a['total_premium_current_month']);
|
|
|
|
final aPrev = isProductWisePolicy
|
|
? parseDouble(a['total_policies_pre_month'])
|
|
: parseDouble(a['total_premium_pre_month']);
|
|
|
|
final bCurrent = isProductWisePolicy
|
|
? parseDouble(b['total_policies_current_month'])
|
|
: parseDouble(b['total_premium_current_month']);
|
|
|
|
final bPrev = isProductWisePolicy
|
|
? parseDouble(b['total_policies_pre_month'])
|
|
: parseDouble(b['total_premium_pre_month']);
|
|
|
|
final aMax = aCurrent > aPrev ? aCurrent : aPrev;
|
|
final bMax = bCurrent > bPrev ? bCurrent : bPrev;
|
|
|
|
return bMax.compareTo(aMax); // DESC
|
|
});
|
|
|
|
return sorted;
|
|
}
|
|
|
|
List<BarData> buildProductBarData(List<Map<String, dynamic>> sortedList) {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
return sortedList.map((item) {
|
|
return BarData(
|
|
Colors.blue,
|
|
isProductWisePolicy
|
|
? parseDouble(item['total_policies_current_month'])
|
|
: parseDouble(item['total_premium_current_month']),
|
|
isProductWisePolicy
|
|
? parseDouble(item['total_policies_pre_month'])
|
|
: parseDouble(item['total_premium_pre_month']),
|
|
item['vehicle_type']?.toString() ?? '',
|
|
'Product',
|
|
10,
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
List<String> buildProductLabels(List<Map<String, dynamic>> sortedList) {
|
|
return sortedList.map<String>((item) {
|
|
return item['vehicle_type']?.toString() ?? '';
|
|
}).toList();
|
|
}
|
|
|
|
List<BarData> buildProductBarData1() {
|
|
double parseDouble(dynamic value) {
|
|
if (value == null) return 0.0;
|
|
if (value is num) return value.toDouble();
|
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
|
return 0.0;
|
|
}
|
|
|
|
return filteredProductWise.map((item) {
|
|
print('policies_current - ${item['total_policies_current_month']}');
|
|
print('policies_PREV - ${item['total_policies_pre_month']}');
|
|
|
|
print('premium_current - ${item['total_premium_current_month']}');
|
|
print('premium_PREV - ${item['total_premium_pre_month']}');
|
|
return BarData(
|
|
Colors.blue,
|
|
isProductWisePolicy
|
|
? parseDouble(item['total_policies_current_month'])
|
|
: parseDouble(item['total_premium_current_month']),
|
|
isProductWisePolicy
|
|
? parseDouble(item['total_policies_pre_month'])
|
|
: parseDouble(item['total_premium_pre_month']),
|
|
item['vehicle_type'] != null ? item['vehicle_type'] : '0',
|
|
'Product',
|
|
10,
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
List<String> buildProductLabels1() {
|
|
return filteredProductWise.map<String>((item) {
|
|
final name = item['vehicle_type'];
|
|
if (name != null && name.toString().trim().isNotEmpty) {
|
|
return name.toString();
|
|
} else {
|
|
return item['vehicle_type']?.toString() ?? '';
|
|
}
|
|
}).toList();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SelectionArea(
|
|
child: Container(
|
|
margin: EdgeInsets.only(left: 10, right: 10, bottom: 10),
|
|
// color: Colors.amber.shade100,
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Spacer(),
|
|
Text('Hide and Show Charts : ', style: _styleSmall1),
|
|
|
|
Row(
|
|
children: [
|
|
Transform.scale(
|
|
scale: 0.75,
|
|
child: Checkbox(
|
|
value: showInsurer,
|
|
onChanged: (val) {
|
|
setState(() => showInsurer = val!);
|
|
},
|
|
),
|
|
),
|
|
Text(
|
|
// showInsurer ? "Insurer" : "Insurer Hidden",
|
|
"Insurer",
|
|
style: _styleSmall2,
|
|
),
|
|
],
|
|
),
|
|
|
|
SizedBox(width: 10),
|
|
|
|
Row(
|
|
children: [
|
|
Transform.scale(
|
|
scale: 0.75,
|
|
child: Checkbox(
|
|
value: showBroker,
|
|
onChanged: (val) {
|
|
setState(() => showBroker = val!);
|
|
},
|
|
),
|
|
),
|
|
Text(
|
|
// showBroker ? "Broker" : "Broker Hidden",
|
|
"Broker",
|
|
style: _styleSmall2,
|
|
),
|
|
],
|
|
),
|
|
|
|
SizedBox(width: 10),
|
|
|
|
Row(
|
|
children: [
|
|
Transform.scale(
|
|
scale: 0.75,
|
|
child: Checkbox(
|
|
value: showProduct,
|
|
onChanged: (val) {
|
|
setState(() => showProduct = val!);
|
|
},
|
|
),
|
|
),
|
|
Text(
|
|
// showProduct ? "Product" : "Product Hidden",
|
|
"Product",
|
|
style: _styleSmall2,
|
|
),
|
|
],
|
|
),
|
|
Spacer(),
|
|
legendWidget(),
|
|
],
|
|
),
|
|
|
|
Expanded(
|
|
child: Row(
|
|
children: [
|
|
(showInsurer || showBroker)
|
|
? Expanded(
|
|
flex: 2,
|
|
child: Column(
|
|
children: [
|
|
showInsurer
|
|
? Expanded(child: insurerContainer())
|
|
: SizedBox(),
|
|
showInsurer ? SizedBox(height: 10) : SizedBox(),
|
|
|
|
showBroker
|
|
? Expanded(child: brokerContainer())
|
|
: SizedBox(),
|
|
],
|
|
),
|
|
)
|
|
: SizedBox(),
|
|
|
|
showProduct
|
|
? Expanded(flex: 1, child: productContainer())
|
|
: SizedBox(),
|
|
],
|
|
),
|
|
),
|
|
|
|
// (showInsurer || showBroker)
|
|
// ? Expanded(
|
|
// child: Row(
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
// children: [
|
|
// // if (showInsurer) Expanded(child: insurerContainer()),
|
|
// // if (showBroker) Expanded(child: brokerContainer()),
|
|
// showInsurer
|
|
// ? Expanded(child: insurerContainer())
|
|
// : SizedBox(),
|
|
// showBroker
|
|
// ? Expanded(child: brokerContainer())
|
|
// : SizedBox(),
|
|
// // showProduct ? Expanded(child: productContainer()) : SizedBox(),
|
|
// ],
|
|
// ),
|
|
// )
|
|
// : SizedBox(),
|
|
|
|
// if (showBroker) ...[
|
|
// SizedBox(height: 10),
|
|
// Expanded(
|
|
// child: Row(
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
// children: [
|
|
// showBroker ? Expanded(child: brokerContainer()) : SizedBox(),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ] else ...[
|
|
// SizedBox.shrink(),
|
|
// ],
|
|
// if (showProduct) ...[
|
|
// SizedBox(height: 10),
|
|
// Expanded(
|
|
// child: Row(
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
// children: [
|
|
// showProduct
|
|
// ? Expanded(child: productContainer())
|
|
// : SizedBox(),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ] else ...[
|
|
// SizedBox.shrink(),
|
|
// ],
|
|
],
|
|
),
|
|
) );
|
|
}
|
|
|
|
Widget insurerContainer() {
|
|
// final chartInsurerData = buildInsurerBarData();
|
|
// final chartInsurerLabels = buildInsurerLabels();
|
|
|
|
final sortedInsurer = getSortedInsurerWise();
|
|
|
|
final chartInsurerData = buildInsurerBarData(sortedInsurer);
|
|
final chartInsurerLabels = buildInsurerLabels(sortedInsurer);
|
|
|
|
print('chartInsurerData - $chartInsurerData');
|
|
print('chartInsurerLabels - $chartInsurerLabels');
|
|
return Card(
|
|
margin: const EdgeInsets.only(right: 10),
|
|
color: Colors.white,
|
|
// color: Colors.amber.shade100,
|
|
elevation: 0.01, // card shadow
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
clipBehavior: Clip.antiAlias,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(child: Text('Insurer-Wise', style: _chartHeader)),
|
|
|
|
// buildInsurer(context),
|
|
Text(
|
|
isInsureWisePolicy ? "Policies" : "Premium",
|
|
style: _styleSmall1,
|
|
),
|
|
Transform.scale(
|
|
scale: 0.5,
|
|
child: Switch(
|
|
value: isInsureWisePolicy,
|
|
onChanged: (val) =>
|
|
setState(() => isInsureWisePolicy = val),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 10),
|
|
Expanded(
|
|
child: Container(
|
|
// color: Colors.amber.shade100,
|
|
clipBehavior: Clip.none,
|
|
// color: Colors.red.shade100,
|
|
child: CustomBarChart(
|
|
dataList: chartInsurerData,
|
|
labels: chartInsurerLabels,
|
|
),
|
|
),
|
|
),
|
|
// legendWidget(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget brokerContainer() {
|
|
// final chartBrokerData = buildBrokerBarData();
|
|
// final chartBrokerLabels = buildBrokerLabels();
|
|
// final chartBrokerShortName = buildBrokerShortNames();
|
|
|
|
final sortedBroker = getSortedBrokerWise();
|
|
|
|
final chartBrokerData = buildBrokerBarData(sortedBroker);
|
|
final chartBrokerLabels = buildBrokerLabels(sortedBroker);
|
|
final chartBrokerShortNames = buildBrokerShortNames(sortedBroker);
|
|
print('chartBrokerData - $chartBrokerData');
|
|
print('chartBrokerLabels - $chartBrokerLabels');
|
|
return Card(
|
|
margin: const EdgeInsets.only(right: 10),
|
|
color: Colors.white,
|
|
elevation: 0.01, // card shadow
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
clipBehavior: Clip.antiAlias,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(child: Text('Broker-Wise', style: _chartHeader)),
|
|
|
|
Text(
|
|
isBrokerWisePolicy ? "Policies" : "Premium",
|
|
style: _styleSmall1,
|
|
),
|
|
Transform.scale(
|
|
scale: 0.5,
|
|
child: Switch(
|
|
value: isBrokerWisePolicy,
|
|
onChanged: (val) =>
|
|
setState(() => isBrokerWisePolicy = val),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 10),
|
|
Expanded(
|
|
child: CustomBarChart(
|
|
dataList: chartBrokerData,
|
|
labels: chartBrokerShortNames,
|
|
shortName: chartBrokerLabels,
|
|
|
|
// labels: chartBrokerLabels,
|
|
// shortName: chartBrokerShortName,
|
|
),
|
|
),
|
|
// legendWidget(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget productContainer() {
|
|
final sortedList = getSortedProductWise();
|
|
|
|
final chartProductData = buildProductBarData(sortedList);
|
|
final chartProductLabels = buildProductLabels(sortedList);
|
|
// final chartProductData = buildProductBarData();
|
|
// final chartProductLabels = buildProductLabels();
|
|
print('chartProductData - $chartProductData');
|
|
print('chartProductLabels - $chartProductLabels');
|
|
return Card(
|
|
margin: const EdgeInsets.only(right: 10),
|
|
color: Colors.white,
|
|
elevation: 0.01, // card shadow
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
clipBehavior: Clip.antiAlias,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(4.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Expanded(child: Text('Product-Wise', style: _chartHeader)),
|
|
Text(
|
|
isProductWisePolicy ? "Policies" : "Premium",
|
|
style: _styleSmall1,
|
|
),
|
|
Transform.scale(
|
|
scale: 0.5,
|
|
child: Switch(
|
|
value: isProductWisePolicy,
|
|
onChanged: (val) =>
|
|
setState(() => isProductWisePolicy = val),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 10),
|
|
Expanded(
|
|
child: CustomBarChartHorizontal(
|
|
dataList: chartProductData,
|
|
labels: chartProductLabels,
|
|
),
|
|
),
|
|
// legendWidget(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget legendWidget() {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Icons.circle,
|
|
size: 10,
|
|
color: Color(0xFF34a9a8),
|
|
// color: Colors.cyan.shade300
|
|
),
|
|
SizedBox(width: 2),
|
|
Text('Current Month', style: _styleSmall1),
|
|
SizedBox(width: 5),
|
|
Icon(
|
|
Icons.circle,
|
|
size: 10,
|
|
// color: Colors.orange.shade300
|
|
color: const Color(0xFFA5E4E1),
|
|
),
|
|
SizedBox(width: 2),
|
|
Text('Previous Month', style: _styleSmall1),
|
|
],
|
|
);
|
|
}
|
|
|
|
// Helper: Insurance plan type dropdown
|
|
Widget buildInsurer(BuildContext context) {
|
|
Map<String, dynamic>? selectedInsurerd = filteredInsurerWise.firstWhere(
|
|
(item) => item['id'].toString() == selectedInsurer,
|
|
orElse: () => {},
|
|
);
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
height: 20,
|
|
width: MediaQuery.of(context).size.width * 0.08,
|
|
child: DropdownSearch<Map<String, dynamic>>(
|
|
key: dropDownKeyInsurer,
|
|
selectedItem: selectedInsurerd.isNotEmpty ? selectedInsurerd : null,
|
|
// items: (filter, infiniteScrollProps) {
|
|
// return filteredInsurersData;
|
|
// },
|
|
items: (filter, infiniteScrollProps) async {
|
|
if (filter.isEmpty) {
|
|
return filteredInsurerWise;
|
|
}
|
|
return filteredInsurerWise.where((item) {
|
|
return item['short_name'].toString().toLowerCase().contains(
|
|
filter.toLowerCase(),
|
|
);
|
|
}).toList();
|
|
},
|
|
|
|
itemAsString: (val) => val['short_name'].toString(), // what to show
|
|
compareFn: (item, selectedItem) =>
|
|
item['id'] == selectedItem['id'], // ✅ compare by id
|
|
validator: (val) {
|
|
if (val == null) {
|
|
return "Required"; // ✅ error message
|
|
}
|
|
return null;
|
|
},
|
|
suffixProps: DropdownSuffixProps(
|
|
// make sure the dropdown button is visible
|
|
dropdownButtonProps: DropdownButtonProps(
|
|
isVisible: true,
|
|
padding: EdgeInsets.zero, // remove default padding
|
|
constraints: const BoxConstraints(
|
|
// shrink icon tap area
|
|
minWidth: 12,
|
|
minHeight: 12,
|
|
),
|
|
iconSize: 15, // smaller icon
|
|
// icon: const Icon(Icons.arrow_drop_down),
|
|
),
|
|
),
|
|
dropdownBuilder: (context, selectedItem) => Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
selectedItem != null
|
|
? selectedItem['short_name'].toString()
|
|
: "",
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 11,
|
|
color: Color(0XFF6366F1),
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 1,
|
|
softWrap: false,
|
|
),
|
|
),
|
|
decoratorProps: DropDownDecoratorProps(
|
|
decoration:
|
|
AppInputDecorations.dropdownDecoration(
|
|
label: "Insurer",
|
|
).copyWith(
|
|
filled: true,
|
|
fillColor:
|
|
Colors.white, // 👈 makes the dropdown input white
|
|
isDense: true,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: const BorderSide(
|
|
color: Color(0XFF6366F1),
|
|
width: 0.5,
|
|
),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: const BorderSide(
|
|
color: Color(0XFF6366F1),
|
|
width: 0.5,
|
|
),
|
|
),
|
|
contentPadding: EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 6,
|
|
),
|
|
),
|
|
),
|
|
|
|
popupProps: PopupProps.menu(
|
|
fit: FlexFit.loose,
|
|
constraints: BoxConstraints(maxHeight: 200),
|
|
menuProps: MenuProps(
|
|
backgroundColor:
|
|
Colors.white, // 👈 sets dropdown background to white
|
|
),
|
|
showSearchBox: true,
|
|
searchFieldProps: TextFieldProps(
|
|
style: GoogleFonts.inter(fontSize: 11, color: Colors.black),
|
|
|
|
autofocus: true,
|
|
decoration: InputDecoration(
|
|
contentPadding: EdgeInsets.all(1),
|
|
filled: true,
|
|
fillColor: Colors.white,
|
|
hintText: "Search Insurer...",
|
|
hintStyle: GoogleFonts.inter(
|
|
fontSize: 12,
|
|
color: Colors.black,
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
color: Colors.white,
|
|
), // 👈 Normal border
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide: BorderSide(
|
|
color: Colors.white,
|
|
width: 1.5,
|
|
), // 👈 Focused border
|
|
),
|
|
),
|
|
),
|
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
|
return Container(
|
|
// color: isSelected ? Colors.blue.withOpacity(0.1) : null,
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 3,
|
|
),
|
|
child: Text(
|
|
item['short_name'].toString(),
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.black),
|
|
),
|
|
);
|
|
},
|
|
// constraints: BoxConstraints(),
|
|
),
|
|
|
|
onChanged: (val) {
|
|
if (val != null) {
|
|
print("Selected Insurer : ${val['name']}");
|
|
print("Id: ${val['id']}");
|
|
selectedInsurer = val['id'];
|
|
// widget.onInsurerChanged?.call(val['id']);
|
|
// controllers['agentId']?.text = val['agent_code'];
|
|
// agentId = agent['id'];
|
|
}
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
List<Map<String, dynamic>> _filterInsurancePlans(String filter) {
|
|
if (filter.isEmpty) return filteredInsuranceData;
|
|
return filteredInsuranceData.where((plan) {
|
|
return plan['insurance_plan_type'].toString().toLowerCase().contains(
|
|
filter.toLowerCase(),
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
DropdownSuffixProps _buildDropdownSuffix() {
|
|
return DropdownSuffixProps(
|
|
dropdownButtonProps: DropdownButtonProps(
|
|
isVisible: true,
|
|
padding: EdgeInsets.zero,
|
|
constraints: BoxConstraints(minWidth: 12, minHeight: 12),
|
|
iconSize: 8,
|
|
color: Colors.black45,
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildDropdownDisplay(dynamic selectedItem, String key, String hint) {
|
|
bool isEmpty =
|
|
selectedItem == null ||
|
|
selectedItem.isEmpty ||
|
|
selectedItem[key] == null;
|
|
|
|
return Container(
|
|
padding: EdgeInsets.zero,
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
isEmpty ? hint : selectedItem[key].toString(),
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 11,
|
|
color: isEmpty ? Colors.grey.shade500 : Colors.black,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 1,
|
|
softWrap: false,
|
|
),
|
|
);
|
|
}
|
|
|
|
DropDownDecoratorProps _buildDropdownDecorator() {
|
|
return DropDownDecoratorProps(
|
|
decoration: AppInputDecorations.dropdownDecoration().copyWith(
|
|
filled: true,
|
|
fillColor: Colors.white,
|
|
isDense: true,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: BorderSide(color: Color(0xFFE2E8F0), width: 0.5),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: BorderSide(color: Color(0xFFE2E8F0), width: 0.5),
|
|
),
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 1, vertical: 6),
|
|
),
|
|
);
|
|
}
|
|
|
|
PopupProps<Map<String, dynamic>> _buildDropdownPopup(String displayKey) {
|
|
return PopupProps.menu(
|
|
fit: FlexFit.loose,
|
|
constraints: BoxConstraints(maxHeight: 300, minWidth: 200),
|
|
menuProps: MenuProps(
|
|
backgroundColor: Colors.white,
|
|
elevation: 8,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
showSearchBox: true,
|
|
searchFieldProps: TextFieldProps(
|
|
autofocus: true,
|
|
decoration: InputDecoration(
|
|
contentPadding: EdgeInsets.all(8),
|
|
filled: true,
|
|
fillColor: Color(0xFFF8FAFC),
|
|
hintText: "Search...",
|
|
hintStyle: GoogleFonts.inter(fontSize: 11, color: Colors.grey),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
borderSide: BorderSide(color: Color(0xFFE2E8F0)),
|
|
),
|
|
),
|
|
),
|
|
itemBuilder: (context, item, isDisabled, isSelected) {
|
|
return Container(
|
|
color: isSelected ? Colors.blue.withOpacity(0.1) : Colors.white,
|
|
padding: EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
|
child: Text(
|
|
item[displayKey].toString(),
|
|
style: GoogleFonts.inter(
|
|
fontSize: 11,
|
|
color: Colors.black87,
|
|
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
final _headerStyle2 = GoogleFonts.poppins(
|
|
fontSize: 12,
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w500,
|
|
);
|
|
final _chartHeader = GoogleFonts.poppins(
|
|
fontSize: 11.5,
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w500,
|
|
);
|
|
final _styleSmall1 = GoogleFonts.poppins(
|
|
fontSize: 10,
|
|
fontWeight: FontWeight.w400,
|
|
);
|
|
|
|
final _styleSmall2 = GoogleFonts.poppins(
|
|
fontSize: 10,
|
|
fontWeight: FontWeight.w400,
|
|
color: Colors.blueGrey,
|
|
);
|