chart clickable changs
This commit is contained in:
parent
dda10c8d91
commit
23fd21b82b
File diff suppressed because one or more lines are too long
@ -4,7 +4,16 @@ class BarData {
|
||||
final Color color;
|
||||
final double value1;
|
||||
final double value2;
|
||||
final String id;
|
||||
final String chartName;
|
||||
|
||||
final double shadowValue;
|
||||
const BarData(this.color, this.value1, this.value2, this.shadowValue);
|
||||
const BarData(
|
||||
this.color,
|
||||
this.value1,
|
||||
this.value2,
|
||||
this.id,
|
||||
this.chartName,
|
||||
this.shadowValue,
|
||||
);
|
||||
}
|
||||
|
||||
@ -9,9 +9,9 @@ class ChartLayoutNotifier extends StateNotifier<List<ChartItem>> {
|
||||
ChartLayoutNotifier() : super(_initialCharts);
|
||||
|
||||
static final List<BarData> _defaultData = [
|
||||
BarData(Colors.blue, 10, 5, 8),
|
||||
BarData(Colors.orange, 12, 6, 10),
|
||||
BarData(Colors.green, 8, 5, 5),
|
||||
BarData(Colors.blue, 10, 5, '4', 'a', 8),
|
||||
BarData(Colors.orange, 12, 6, '5', 'b', 10),
|
||||
BarData(Colors.green, 8, 5, '6', 'c', 5),
|
||||
];
|
||||
|
||||
static final List<ChartItem> _initialCharts = [
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
@ -9,6 +10,7 @@ import '../../../../core/services/api_service.dart';
|
||||
import '../../../../data/models/bar_data.dart';
|
||||
import '../../../providers/userRoleProvider.dart';
|
||||
import '../../../themes/charts/barChart.dart';
|
||||
import '../../../themes/indicators/input_field_decoration.dart';
|
||||
|
||||
class BussinessDashboard extends ConsumerStatefulWidget {
|
||||
const BussinessDashboard({super.key});
|
||||
@ -21,6 +23,8 @@ 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 = [];
|
||||
@ -39,6 +43,12 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
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;
|
||||
@ -175,6 +185,8 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
isInsureWisePolicy
|
||||
? parseDouble(item['total_policies_pre_month'])
|
||||
: parseDouble(item['total_premium_pre_month']),
|
||||
item['insurer_id'] != null ? item['insurer_id'] : '0',
|
||||
'Insurer',
|
||||
5,
|
||||
);
|
||||
}).toList();
|
||||
@ -213,6 +225,8 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
isBrokerWisePolicy
|
||||
? parseDouble(item['total_policies_pre_month'])
|
||||
: parseDouble(item['total_premium_pre_month']),
|
||||
item['broker_id'] != null ? item['broker_id'] : '0',
|
||||
'Broker',
|
||||
5,
|
||||
);
|
||||
}).toList();
|
||||
@ -251,6 +265,8 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
isProductWisePolicy
|
||||
? parseDouble(item['total_policies_pre_month'])
|
||||
: parseDouble(item['total_premium_pre_month']),
|
||||
item['vehicle_type'] != null ? item['vehicle_type'] : '0',
|
||||
'Product',
|
||||
10,
|
||||
);
|
||||
}).toList();
|
||||
@ -362,51 +378,64 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
final chartInsurerLabels = buildInsurerLabels();
|
||||
print('chartInsurerData - $chartInsurerData');
|
||||
print('chartInsurerLabels - $chartInsurerLabels');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(right: 20),
|
||||
clipBehavior: Clip.none,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Insurer Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
color: Colors.white,
|
||||
elevation: 1, // card shadow
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Insurer Wise', style: _chartHeader),
|
||||
Text(
|
||||
'(Previous / Current Month)',
|
||||
style: _chartHeader.copyWith(
|
||||
color: Colors.black87,
|
||||
fontSize: 8,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
isInsureWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isInsureWisePolicy,
|
||||
onChanged: (val) => setState(() => isInsureWisePolicy = val),
|
||||
|
||||
// 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(
|
||||
clipBehavior: Clip.none,
|
||||
// color: Colors.red.shade100,
|
||||
child: CustomBarChart(
|
||||
dataList: chartInsurerData,
|
||||
labels: chartInsurerLabels,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: Container(
|
||||
clipBehavior: Clip.none,
|
||||
// color: Colors.red.shade100,
|
||||
child: CustomBarChart(
|
||||
dataList: chartInsurerData,
|
||||
labels: chartInsurerLabels,
|
||||
),
|
||||
),
|
||||
),
|
||||
legendWidget(),
|
||||
],
|
||||
legendWidget(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -416,46 +445,50 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
final chartBrokerLabels = buildBrokerLabels();
|
||||
print('chartBrokerData - $chartBrokerData');
|
||||
print('chartBrokerLabels - $chartBrokerLabels');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(right: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Broker Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
color: Colors.white,
|
||||
elevation: 1, // card shadow
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Broker Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
isBrokerWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isBrokerWisePolicy,
|
||||
onChanged: (val) => setState(() => isBrokerWisePolicy = val),
|
||||
|
||||
Text(
|
||||
isBrokerWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomBarChart(
|
||||
dataList: chartBrokerData,
|
||||
labels: chartBrokerLabels,
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isBrokerWisePolicy,
|
||||
onChanged: (val) =>
|
||||
setState(() => isBrokerWisePolicy = val),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
legendWidget(),
|
||||
],
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomBarChart(
|
||||
dataList: chartBrokerData,
|
||||
labels: chartBrokerLabels,
|
||||
),
|
||||
),
|
||||
legendWidget(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -465,46 +498,49 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
final chartProductLabels = buildProductLabels();
|
||||
print('chartProductData - $chartProductData');
|
||||
print('chartProductLabels - $chartProductLabels');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(right: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Product Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
color: Colors.white,
|
||||
elevation: 1, // card shadow
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Product Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
isProductWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isProductWisePolicy,
|
||||
onChanged: (val) => setState(() => isProductWisePolicy = val),
|
||||
Text(
|
||||
isProductWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomBarChart(
|
||||
dataList: chartProductData,
|
||||
labels: chartProductLabels,
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isProductWisePolicy,
|
||||
onChanged: (val) =>
|
||||
setState(() => isProductWisePolicy = val),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
legendWidget(),
|
||||
],
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomBarChart(
|
||||
dataList: chartProductData,
|
||||
labels: chartProductLabels,
|
||||
),
|
||||
),
|
||||
legendWidget(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -523,6 +559,273 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 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(
|
||||
|
||||
@ -300,6 +300,8 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
isInsureWisePolicy
|
||||
? parseDouble(item['total_policies_pre_month'])
|
||||
: parseDouble(item['total_premium_pre_month']),
|
||||
item['vehicle_type'] != null ? item['vehicle_type'] : 0,
|
||||
'Productivity',
|
||||
5,
|
||||
);
|
||||
}).toList();
|
||||
@ -327,6 +329,8 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
isProductWisePolicy
|
||||
? parseDouble(item['total_policies_pre_month'])
|
||||
: parseDouble(item['total_premium_pre_month']),
|
||||
item['vehicle_type'],
|
||||
'Productivity',
|
||||
10,
|
||||
);
|
||||
}).toList();
|
||||
@ -416,59 +420,61 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
final chartStaffData = buildStaffBarData();
|
||||
final chartStaffLabels = buildStaffLabels();
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(right: 20),
|
||||
clipBehavior: Clip.none,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Sales Executive Product Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(right: 10),
|
||||
color: Colors.white,
|
||||
shadowColor: Colors.black,
|
||||
elevation: 1, // card shadow
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Sales Executive Product Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
isInsureWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isInsureWisePolicy,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
isInsureWisePolicy = val;
|
||||
});
|
||||
// 👇 ADD THIS: Rebuild chart data with new toggle value
|
||||
getProductivityDashBrdList(managerId);
|
||||
},
|
||||
Text(
|
||||
isInsureWisePolicy ? "Policies" : "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomStackedBarChart(
|
||||
labels: staffLabels,
|
||||
// maxY: (maxPremium * 1.1).ceilToDouble(),
|
||||
maxY: _getSmartMaxValue(),
|
||||
initialRotation: 1,
|
||||
dataList: [],
|
||||
productsList: staffChartData,
|
||||
vehicleTypeNames:
|
||||
staffVehicleTypeNames, // 👈 NEW: Pass vehicle names
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isInsureWisePolicy,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
isInsureWisePolicy = val;
|
||||
});
|
||||
// 👇 ADD THIS: Rebuild chart data with new toggle value
|
||||
getProductivityDashBrdList(managerId);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(children: [Expanded(child: legendWidget())]),
|
||||
],
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomStackedBarChart(
|
||||
labels: staffLabels,
|
||||
// maxY: (maxPremium * 1.1).ceilToDouble(),
|
||||
maxY: _getSmartMaxValue(),
|
||||
initialRotation: 1,
|
||||
dataList: [],
|
||||
productsList: staffChartData,
|
||||
vehicleTypeNames:
|
||||
staffVehicleTypeNames, // 👈 NEW: Pass vehicle names
|
||||
),
|
||||
),
|
||||
Row(children: [Expanded(child: legendWidget())]),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -555,7 +555,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
final yesterday = today.subtract(Duration(days: 1));
|
||||
|
||||
fromDt = dateFormat.format(yesterday.subtract(Duration(days: 2)));
|
||||
fromDt = dateFormat.format(yesterday.subtract(Duration(days: 15)));
|
||||
toDt = dateFormat.format(yesterday);
|
||||
|
||||
print('PrevPending FROM TO - $fromDt - $toDt');
|
||||
@ -578,7 +578,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print("ENQ LIST PAGE");
|
||||
|
||||
final today = DateTime.now();
|
||||
fromDt = dateFormat.format(today.subtract(Duration(days: 2)));
|
||||
fromDt = dateFormat.format(today.subtract(Duration(days: 5)));
|
||||
// fromDt = dateFormat.format(today);
|
||||
toDt = dateFormat.format(today);
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ class policylistState extends ConsumerState<policylist> {
|
||||
}
|
||||
|
||||
Future.microtask(() {
|
||||
final managerId = ref.read(managerIdProvider);
|
||||
managerId = ref.read(managerIdProvider);
|
||||
roleId = ref.read(userRoleProvider);
|
||||
userId = ref.read(userIdProvider);
|
||||
|
||||
@ -194,6 +194,7 @@ class policylistState extends ConsumerState<policylist> {
|
||||
}
|
||||
|
||||
void filterDateRange() {
|
||||
print('filterDateRange');
|
||||
// ✅ Validate the form first
|
||||
// if (!_formKey.currentState!.validate()) {
|
||||
// // stop execution if validation fails
|
||||
@ -216,7 +217,16 @@ class policylistState extends ConsumerState<policylist> {
|
||||
// }
|
||||
|
||||
// ✅ Call your API
|
||||
getStaffList(managerId, userId, roleId);
|
||||
// getStaffList(managerId, userId, roleId);
|
||||
|
||||
// print("D61 => r : $roleId | mId: $id | uId: $userId");
|
||||
if (userId != null && managerId != null) {
|
||||
print('filterDateRange 1s');
|
||||
print('manager - $managerId - userID -$userId - roledId -$roleId');
|
||||
|
||||
getStaffList(managerId!, userId, roleId);
|
||||
}
|
||||
print('filterDateRange 1');
|
||||
}
|
||||
|
||||
void refrshfilterDateRange() {
|
||||
@ -425,6 +435,7 @@ class policylistState extends ConsumerState<policylist> {
|
||||
formKey: _formKey,
|
||||
isMobile: ResponsiveLayout.isMobile(context),
|
||||
onFilter: () {
|
||||
print('onFilter');
|
||||
// call your filter logic
|
||||
filterDateRange();
|
||||
},
|
||||
|
||||
@ -32,11 +32,15 @@ class CustomBarChart extends StatefulWidget {
|
||||
class _CustomBarChartState extends State<CustomBarChart> {
|
||||
int touchedGroupIndex = -1;
|
||||
late int rotationTurns;
|
||||
dynamic managerId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
rotationTurns = widget.initialRotation;
|
||||
// Future.microtask(() {
|
||||
// managerId = ref.read(managerIdProvider);
|
||||
// });
|
||||
}
|
||||
|
||||
BarChartGroupData generateBarGroup(
|
||||
@ -53,7 +57,6 @@ class _CustomBarChartState extends State<CustomBarChart> {
|
||||
// barsSpace: 30,
|
||||
barRods: [
|
||||
BarChartRodData(toY: value1, color: Colors.cyan.shade300, width: 4),
|
||||
|
||||
// BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6),
|
||||
BarChartRodData(toY: value2, color: Colors.orange.shade300, width: 4),
|
||||
],
|
||||
@ -71,27 +74,6 @@ class _CustomBarChartState extends State<CustomBarChart> {
|
||||
// verticalAxis: Axis.horizontal,
|
||||
rotationQuarterTurns: rotationTurns,
|
||||
|
||||
// barTouchData: BarTouchData(
|
||||
// // 1. Disable built-in touch handling
|
||||
// handleBuiltInTouches: false,
|
||||
// touchTooltipData: BarTouchTooltipData(
|
||||
// // 3. Define the tooltip content
|
||||
// getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||
// // You can customize the content here
|
||||
// return BarTooltipItem(
|
||||
// '${rod.toY.round().toString()}', // Explicit value
|
||||
// GoogleFonts.poppins(
|
||||
// color: Colors.black,
|
||||
// fontSize: 8,
|
||||
// fontWeight: FontWeight.w500,
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// // Customize appearance
|
||||
// getTooltipColor: (BarChartGroupData group) => Colors.transparent,
|
||||
// tooltipRoundedRadius: 8,
|
||||
// ),
|
||||
// ),
|
||||
barTouchData: BarTouchData(
|
||||
enabled: true,
|
||||
handleBuiltInTouches: true,
|
||||
@ -124,6 +106,7 @@ class _CustomBarChartState extends State<CustomBarChart> {
|
||||
return BarTooltipItem('${rod.toY.round()}', textStyle);
|
||||
},
|
||||
),
|
||||
|
||||
touchCallback: (FlTouchEvent e, BarTouchResponse? r) {
|
||||
// optional: change state to highlight tapped group
|
||||
if (r == null || r.spot == null) {
|
||||
@ -131,6 +114,20 @@ class _CustomBarChartState extends State<CustomBarChart> {
|
||||
return;
|
||||
}
|
||||
setState(() => touchedGroupIndex = r.spot!.touchedBarGroupIndex);
|
||||
|
||||
final spot = r.spot!;
|
||||
final groupIndex = spot.touchedBarGroupIndex;
|
||||
final rodIndex = spot.touchedRodDataIndex;
|
||||
|
||||
final barData = widget.dataList[groupIndex];
|
||||
|
||||
if (e is FlTapUpEvent) {
|
||||
debugPrint(
|
||||
'Tapped value → ${rodIndex == 0 ? barData.value1 : barData.value2} -> ${barData.id}-'
|
||||
' ${rodIndex == 0 ? 'current' : 'previous'} -> ${barData.chartName}',
|
||||
);
|
||||
// await apiService.generateExcel()
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user