claims/endorsment salesExecChart
This commit is contained in:
parent
3477cd99f3
commit
8cc66eb233
File diff suppressed because one or more lines are too long
@ -1166,6 +1166,47 @@ class ApiService {
|
|||||||
|
|
||||||
// ----------------------------------- CLAIMS -------------------------------------------------
|
// ----------------------------------- CLAIMS -------------------------------------------------
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchPolicySearch(val) async {
|
||||||
|
// print(_token);
|
||||||
|
|
||||||
|
// print('rolemanagerId - $managerId');
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic url;
|
||||||
|
url = Uri.parse('${Env.apiUrl}policy/searchThePolicies?policy_number=$val');
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchVehicleSearch(val) async {
|
||||||
|
// print(_token);
|
||||||
|
|
||||||
|
// print('rolemanagerId - $managerId');
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic url;
|
||||||
|
|
||||||
|
url = Uri.parse(
|
||||||
|
'${Env.apiUrl}policy/searchThePolicies?vehicle_number=$val',
|
||||||
|
);
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchClaimList(int id, role) async {
|
Future<Map<String, dynamic>> fetchClaimList(int id, role) async {
|
||||||
// print(_token);
|
// print(_token);
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class AddDialog extends StatefulWidget {
|
|||||||
final dynamic managerId;
|
final dynamic managerId;
|
||||||
final dynamic role;
|
final dynamic role;
|
||||||
final void Function(String value) onSubmit;
|
final void Function(String value) onSubmit;
|
||||||
final dynamic policyNumber;
|
// final dynamic policyNumber;
|
||||||
const AddDialog({
|
const AddDialog({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
@ -34,7 +34,7 @@ class AddDialog extends StatefulWidget {
|
|||||||
required this.userId,
|
required this.userId,
|
||||||
required this.managerId,
|
required this.managerId,
|
||||||
required this.role,
|
required this.role,
|
||||||
this.policyNumber,
|
// this.policyNumber,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -69,6 +69,10 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
|
|
||||||
List<String> tabHeader = ['policyNum', 'claimsDesc', 'remarks'];
|
List<String> tabHeader = ['policyNum', 'claimsDesc', 'remarks'];
|
||||||
|
|
||||||
|
final TextEditingController _vehicleSearchController =
|
||||||
|
TextEditingController();
|
||||||
|
final TextEditingController _policySearchController = TextEditingController();
|
||||||
|
|
||||||
final TextEditingController _searchStaffController = TextEditingController();
|
final TextEditingController _searchStaffController = TextEditingController();
|
||||||
|
|
||||||
List<Map<String, dynamic>> getClaimsTypeData = [];
|
List<Map<String, dynamic>> getClaimsTypeData = [];
|
||||||
@ -86,6 +90,14 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
List<Map<String, dynamic>> originalData = [];
|
List<Map<String, dynamic>> originalData = [];
|
||||||
List<Map<String, dynamic>> filteredData = [];
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> getPolicyListData = [];
|
||||||
|
List<Map<String, dynamic>> originalPolicyData = [];
|
||||||
|
List<Map<String, dynamic>> filteredPolicyData = [];
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> getVehicleListData = [];
|
||||||
|
List<Map<String, dynamic>> originalVehicleData = [];
|
||||||
|
List<Map<String, dynamic>> filteredVehicleData = [];
|
||||||
|
|
||||||
Map<String, dynamic> claimsDetails() {
|
Map<String, dynamic> claimsDetails() {
|
||||||
final data = {
|
final data = {
|
||||||
"policy_number": controllers["policyNum"]?.text,
|
"policy_number": controllers["policyNum"]?.text,
|
||||||
@ -116,7 +128,7 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
controllers[field] = TextEditingController();
|
controllers[field] = TextEditingController();
|
||||||
}
|
}
|
||||||
|
|
||||||
controllers["policyNum"]?.text = widget.policyNumber;
|
// controllers["policyNum"]?.text = widget.policyNumber;
|
||||||
print('userIFF - ${widget.userId}');
|
print('userIFF - ${widget.userId}');
|
||||||
print('roleIFF - ${widget.role}');
|
print('roleIFF - ${widget.role}');
|
||||||
|
|
||||||
@ -136,6 +148,107 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
getEnroementType();
|
getEnroementType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> getPolicyListSearchData(String val) async {
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchPolicySearch(val);
|
||||||
|
|
||||||
|
if (response['status'] == 'success' && response['data'] != null) {
|
||||||
|
final dataList = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
setState(() {
|
||||||
|
getPolicyListData = dataList;
|
||||||
|
originalPolicyData = dataList;
|
||||||
|
filteredPolicyData = List.from(originalPolicyData);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
getPolicyListData = [];
|
||||||
|
originalPolicyData = [];
|
||||||
|
filteredPolicyData = [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
setState(() {
|
||||||
|
getPolicyListData = [];
|
||||||
|
originalPolicyData = [];
|
||||||
|
filteredPolicyData = [];
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getPolicyListSearchData1(val) async {
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchPolicySearch(val);
|
||||||
|
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
print('E113 => getStaffListData => ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getPolicyListData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
// filteredData = getPolicyData.where((item) {
|
||||||
|
// return (item['agent_name'] ?? '-').toLowerCase() ||
|
||||||
|
// (item['reg_no'] ?? '-').toLowerCase;
|
||||||
|
// }).toList();
|
||||||
|
|
||||||
|
originalPolicyData = getPolicyListData;
|
||||||
|
filteredPolicyData = List.from(originalPolicyData);
|
||||||
|
// print('originalData - $getClaimPolicies');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getPolicyListData = [];
|
||||||
|
originalPolicyData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getVehicleListSearchData(String val) async {
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchVehicleSearch(val);
|
||||||
|
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
print('E113 => getStaffListData => ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getVehicleListData = List<Map<String, dynamic>>.from(
|
||||||
|
response['data'],
|
||||||
|
);
|
||||||
|
originalVehicleData = getVehicleListData;
|
||||||
|
filteredVehicleData = List.from(originalVehicleData);
|
||||||
|
// print('originalData - $getClaimPolicies');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getVehicleListData = [];
|
||||||
|
originalVehicleData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> getStaffList(
|
Future<void> getStaffList(
|
||||||
dynamic managerId,
|
dynamic managerId,
|
||||||
role, {
|
role, {
|
||||||
@ -473,20 +586,160 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ThemedSearchField(
|
Row(
|
||||||
hintText: 'Search',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// backgroundColor: Color(0xFFF6F8F8),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
backgroundColor: Color(0xFFFFFFFF),
|
children: [
|
||||||
txtHeight: 30,
|
Column(
|
||||||
onChanged: filterData,
|
children: [
|
||||||
controller: _searchStaffController,
|
ThemedSearchField(
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
hintText: 'Search By Vehicle Number',
|
||||||
? null
|
backgroundColor: Color(0xFFFFFFFF),
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
txtHeight: 30,
|
||||||
// txtwidth: ResponsiveLayout.isMobile(context)
|
controller: _vehicleSearchController,
|
||||||
// ? MediaQuery.of(context).size.width * 0.7
|
onChanged: (val) async {
|
||||||
// : MediaQuery.of(context).size.width * 0.15,
|
if (val.isNotEmpty) {
|
||||||
|
await getVehicleListSearchData(val);
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
// filteredVehicleData = List.from(originalVehicleData);
|
||||||
|
filteredVehicleData.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.26,
|
||||||
|
),
|
||||||
|
// Vehicle Search Results
|
||||||
|
if (filteredVehicleData.isNotEmpty)
|
||||||
|
Container(
|
||||||
|
width:
|
||||||
|
MediaQuery.of(context).size.width * 0.26, // optional
|
||||||
|
height: 150,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(color: Colors.blueGrey.shade100),
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: filteredVehicleData.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final vehicle = filteredVehicleData[index];
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
controllers['policyNum']?.text =
|
||||||
|
vehicle['policy_number'];
|
||||||
|
filteredVehicleData.clear();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 3,
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Text(
|
||||||
|
vehicle['policy_number'] ?? '-',
|
||||||
|
style: _textStyle1,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
ThemedSearchField(
|
||||||
|
hintText: 'Search By Policy Number',
|
||||||
|
backgroundColor: Color(0xFFFFFFFF),
|
||||||
|
txtHeight: 30,
|
||||||
|
controller: _policySearchController,
|
||||||
|
onChanged: (val) async {
|
||||||
|
if (val.isNotEmpty) {
|
||||||
|
await getPolicyListSearchData(val);
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
// filteredPolicyData = List.from(originalPolicyData);
|
||||||
|
filteredPolicyData.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
|
? null
|
||||||
|
: MediaQuery.of(context).size.width * 0.26,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Policy Search Results
|
||||||
|
if (filteredPolicyData.isNotEmpty)
|
||||||
|
Container(
|
||||||
|
width:
|
||||||
|
MediaQuery.of(context).size.width * 0.26, // optional
|
||||||
|
height: 150,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(color: Colors.blueGrey.shade100),
|
||||||
|
borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: filteredPolicyData.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final policy = filteredPolicyData[index];
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
controllers['policyNum']?.text =
|
||||||
|
policy['policy_number'];
|
||||||
|
filteredPolicyData.clear();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 3,
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
// color: Colors.amber,
|
||||||
|
child: Text(
|
||||||
|
policy['policy_number'] ?? '-',
|
||||||
|
style: _textStyle1,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// ListTile(
|
||||||
|
// dense: true, // ← reduces row height
|
||||||
|
// contentPadding: EdgeInsets.symmetric(
|
||||||
|
// horizontal: 10,
|
||||||
|
// vertical: 2,
|
||||||
|
// ),
|
||||||
|
// subtitle: Text(
|
||||||
|
//
|
||||||
|
// style: _textStyle1,
|
||||||
|
// ),
|
||||||
|
// onTap: () {
|
||||||
|
// setState(() {
|
||||||
|
//
|
||||||
|
// // populate other fields as needed
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// 🔹 Switch content dynamically
|
// 🔹 Switch content dynamically
|
||||||
@ -519,10 +772,24 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
key: _formKeyClaims,
|
key: _formKeyClaims,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
buildClaimType(context),
|
Row(
|
||||||
buildPolicyNumber(context),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
buildUploadDocumentClaims(context),
|
children: [
|
||||||
buildClaimsDesc(context),
|
buildClaimType(context),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
buildPolicyNumber(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
buildUploadDocumentClaims(context),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
buildClaimsDesc(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -534,9 +801,24 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
key: _formKeyEndrosment,
|
key: _formKeyEndrosment,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
buildEndrosType(context),
|
Row(
|
||||||
buildUploadDocumentEndorsment(context),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
buildEndrosRemarks(context),
|
children: [
|
||||||
|
buildEndrosType(context),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
buildPolicyNumber(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
buildUploadDocumentClaims(context),
|
||||||
|
SizedBox(width: 15),
|
||||||
|
buildEndrosRemarks(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -547,7 +829,7 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Policy Number", style: _textStyle),
|
Text("Policy Number *", style: _textStyle),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
controller: controllers['policyNum']!,
|
controller: controllers['policyNum']!,
|
||||||
@ -566,11 +848,12 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Claims Description *", style: _textStyle),
|
Text("Claims Description ", style: _textStyle),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
ThemedFormField(
|
ThemedFormField(
|
||||||
backgroundColor: Color(0xFFEDF6F5),
|
backgroundColor: Color(0xFFEDF6F5),
|
||||||
controller: controllers['claimsDesc']!,
|
controller: controllers['claimsDesc']!,
|
||||||
|
txtheight: 45,
|
||||||
validator: (value) => Validators.requiredField(value, "claimsDesc"),
|
validator: (value) => Validators.requiredField(value, "claimsDesc"),
|
||||||
txtwidth: ResponsiveLayout.isMobile(context)
|
txtwidth: ResponsiveLayout.isMobile(context)
|
||||||
? null
|
? null
|
||||||
@ -860,6 +1143,7 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
? null
|
? null
|
||||||
: MediaQuery.of(context).size.width * 0.26,
|
: MediaQuery.of(context).size.width * 0.26,
|
||||||
keyboardType: TextInputType.multiline,
|
keyboardType: TextInputType.multiline,
|
||||||
|
txtheight: 45,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -952,4 +1236,8 @@ class _AddDialogState extends State<AddDialog> {
|
|||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
);
|
);
|
||||||
|
static final TextStyle _textStyle1 = TextStyle(
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -581,7 +581,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
|||||||
role: null,
|
role: null,
|
||||||
managerId: null,
|
managerId: null,
|
||||||
title: "Endorsement",
|
title: "Endorsement",
|
||||||
policyNumber: selectedPolicyNumber,
|
// policyNumber: selectedPolicyNumber,
|
||||||
onSubmit: (value) {
|
onSubmit: (value) {
|
||||||
debugPrint("New Endorsement: $value");
|
debugPrint("New Endorsement: $value");
|
||||||
enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
||||||
@ -608,7 +608,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
|||||||
title: "Claims",
|
title: "Claims",
|
||||||
role: null,
|
role: null,
|
||||||
managerId: null,
|
managerId: null,
|
||||||
policyNumber: selectedPolicyNumber,
|
// policyNumber: selectedPolicyNumber,
|
||||||
onSubmit: (value) {
|
onSubmit: (value) {
|
||||||
debugPrint("New Claim: $value");
|
debugPrint("New Claim: $value");
|
||||||
claimsKey.currentState?.getClaimsList(selectedPolicyNumber);
|
claimsKey.currentState?.getClaimsList(selectedPolicyNumber);
|
||||||
|
|||||||
@ -175,6 +175,10 @@ class claimListState extends ConsumerState<claimList> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
getStaffList(managerId, userId);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MainLayout(
|
return MainLayout(
|
||||||
@ -303,10 +307,12 @@ class claimListState extends ConsumerState<claimList> {
|
|||||||
userId: userId,
|
userId: userId,
|
||||||
role: roleId,
|
role: roleId,
|
||||||
title: "Claims",
|
title: "Claims",
|
||||||
policyNumber: 'POC_n1',
|
// policyNumber: 'POC_n1',
|
||||||
// policyNumber: selectedPolicyNumber,
|
// policyNumber: selectedPolicyNumber,
|
||||||
onSubmit: (value) {
|
onSubmit: (value) {
|
||||||
debugPrint("New Claims: $value");
|
debugPrint("New Claims: $value");
|
||||||
|
|
||||||
|
refresh();
|
||||||
// enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
// enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
||||||
|
|
||||||
// Update claim list or call API
|
// Update claim list or call API
|
||||||
|
|||||||
@ -111,6 +111,10 @@ class endosementState extends ConsumerState<endosement> {
|
|||||||
return sortedData.sublist(startIndex, endIndex);
|
return sortedData.sublist(startIndex, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
getStaffList(managerId, roleId);
|
||||||
|
}
|
||||||
|
|
||||||
void filterData(String query) {
|
void filterData(String query) {
|
||||||
print("FilterDAta - $query");
|
print("FilterDAta - $query");
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -293,12 +297,12 @@ class endosementState extends ConsumerState<endosement> {
|
|||||||
userId: userId,
|
userId: userId,
|
||||||
role: roleId,
|
role: roleId,
|
||||||
title: "Endorsement",
|
title: "Endorsement",
|
||||||
policyNumber: '1',
|
// policyNumber: '1',
|
||||||
// policyNumber: selectedPolicyNumber,
|
// policyNumber: selectedPolicyNumber,
|
||||||
onSubmit: (value) {
|
onSubmit: (value) {
|
||||||
debugPrint("New Endorsement: $value");
|
debugPrint("New Endorsement: $value");
|
||||||
// enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
// enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
||||||
|
refresh();
|
||||||
// Update claim list or call API
|
// Update claim list or call API
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -324,39 +324,46 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.only(
|
||||||
Expanded(
|
top: 8.0,
|
||||||
child: Text(
|
bottom: 16.0,
|
||||||
'Performing Partner ( Top 50 )',
|
),
|
||||||
style: _chartHeader,
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Performing Partner ( Top 50 )',
|
||||||
|
style: _chartHeader,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
Text(
|
// Text(
|
||||||
isPerfomingAgntPolicy
|
// isPerfomingAgntPolicy
|
||||||
? "Policies"
|
// ? "Policies"
|
||||||
: "Premium",
|
// : "Premium",
|
||||||
style: _styleSmall1,
|
// style: _styleSmall1,
|
||||||
),
|
// ),
|
||||||
|
//
|
||||||
Transform.scale(
|
// Transform.scale(
|
||||||
scale: 0.5,
|
// scale: 0.5,
|
||||||
child: Switch(
|
// child: Switch(
|
||||||
value: isPerfomingAgntPolicy,
|
// value: isPerfomingAgntPolicy,
|
||||||
activeColor: Colors.teal,
|
// activeColor: Colors.teal,
|
||||||
activeTrackColor: Colors.grey.shade200,
|
// activeTrackColor: Colors.grey.shade200,
|
||||||
inactiveThumbColor: Colors.orange,
|
// inactiveThumbColor: Colors.orange,
|
||||||
inactiveTrackColor: Colors.white,
|
// inactiveTrackColor: Colors.white,
|
||||||
onChanged: (val) {
|
// onChanged: (val) {
|
||||||
setState(
|
// setState(
|
||||||
() => isPerfomingAgntPolicy = val,
|
// () => isPerfomingAgntPolicy = val,
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Performance(
|
child: Performance(
|
||||||
title: "Performing Partner",
|
title: "Performing Partner",
|
||||||
@ -518,20 +525,24 @@ class _PerformanceState extends State<Performance> {
|
|||||||
style: _headerStyle,
|
style: _headerStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (widget.title == 'Performing Partner') ...[
|
||||||
(widget.title == 'Performing Partner')
|
Expanded(
|
||||||
? Expanded(
|
flex: 1,
|
||||||
flex: 1,
|
child: Text(
|
||||||
child: Text(
|
"Policy Count",
|
||||||
widget.isPerfomingAgntPolicy
|
textAlign: TextAlign.center,
|
||||||
? "Policy Count"
|
style: _headerStyle,
|
||||||
: "Premium Count",
|
),
|
||||||
|
),
|
||||||
textAlign: TextAlign.center,
|
Expanded(
|
||||||
style: _headerStyle,
|
flex: 1,
|
||||||
),
|
child: Text(
|
||||||
)
|
"Premium Amount",
|
||||||
: SizedBox(),
|
textAlign: TextAlign.center,
|
||||||
|
style: _headerStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -586,30 +597,47 @@ class _PerformanceState extends State<Performance> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
(widget.title == 'Performing Partner')
|
if (widget.title == 'Performing Partner') ...[
|
||||||
? Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Text(
|
child: Text(
|
||||||
isPerfomingAgntPolicy
|
row['policy_count'] ?? "",
|
||||||
? (row['policy_count']?.toString() ?? "0")
|
textAlign: TextAlign.center,
|
||||||
: (row['total_premium_amount']
|
style: _tableDataStyle,
|
||||||
?.toString() ??
|
),
|
||||||
"0"),
|
),
|
||||||
|
Expanded(
|
||||||
textAlign: TextAlign.center,
|
flex: 1,
|
||||||
style: GoogleFonts.inter(
|
child: Text(
|
||||||
fontSize: 11,
|
row['total_premium_amount'] ?? "",
|
||||||
fontWeight: FontWeight.w500,
|
textAlign: TextAlign.center,
|
||||||
// color: isPerfomingAgntPolicy
|
style: _tableDataStyle,
|
||||||
// ? Colors.black
|
),
|
||||||
// : (row['status']?.toString().toLowerCase() ==
|
),
|
||||||
// "active"
|
],
|
||||||
// ? Colors.green
|
// (widget.title == 'Performing Partner')
|
||||||
// : Colors.red),
|
// ? Expanded(
|
||||||
),
|
// flex: 1,
|
||||||
),
|
// child: Text(
|
||||||
)
|
// isPerfomingAgntPolicy
|
||||||
: SizedBox(),
|
// ? (row['policy_count']?.toString() ?? "0")
|
||||||
|
// : (row['total_premium_amount']
|
||||||
|
// ?.toString() ??
|
||||||
|
// "0"),
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// style: GoogleFonts.inter(
|
||||||
|
// fontSize: 11,
|
||||||
|
// fontWeight: FontWeight.w500,
|
||||||
|
// // color: isPerfomingAgntPolicy
|
||||||
|
// // ? Colors.black
|
||||||
|
// // : (row['status']?.toString().toLowerCase() ==
|
||||||
|
// // "active"
|
||||||
|
// // ? Colors.green
|
||||||
|
// // : Colors.red),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// : SizedBox(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -43,9 +43,14 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
|
|
||||||
bool showStaff = true;
|
bool showStaff = true;
|
||||||
bool showProduct = true;
|
bool showProduct = true;
|
||||||
|
int selectedStaffIndex = 0;
|
||||||
|
List<List<String>> staffVehicleTypeNames =
|
||||||
|
[]; // 👈 Add this at the top with other state variables
|
||||||
|
Map<String, Color> vehicleColors = {};
|
||||||
List<String> staffLabels = [];
|
List<String> staffLabels = [];
|
||||||
|
// List<List<List<dynamic>>> staffChartData = [];
|
||||||
List<List<List<dynamic>>> staffChartData = [];
|
List<List<List<dynamic>>> staffChartData = [];
|
||||||
|
|
||||||
double maxPremium = 0;
|
double maxPremium = 0;
|
||||||
|
|
||||||
int selectedView = 0;
|
int selectedView = 0;
|
||||||
@ -74,137 +79,171 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add this helper method:
|
||||||
|
double _getSmartMaxValue() {
|
||||||
|
if (maxPremium <= 0) return 10;
|
||||||
|
|
||||||
|
// For policies (small numbers), ensure minimum scale
|
||||||
|
if (isInsureWisePolicy) {
|
||||||
|
if (maxPremium < 10) {
|
||||||
|
return 12; // Minimum scale of 10 for policies
|
||||||
|
}
|
||||||
|
// Round up to nearest 5
|
||||||
|
return ((maxPremium / 5).ceil() * 5).toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For premium (large numbers)
|
||||||
|
return (maxPremium * 1.15).ceilToDouble(); // 15% headroom
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _generateColorForVehicle(String vehicleType, int index) {
|
||||||
|
// Predefined colors for common vehicle types
|
||||||
|
const predefinedColors = [
|
||||||
|
Colors.blue,
|
||||||
|
Colors.green,
|
||||||
|
Colors.orange,
|
||||||
|
Colors.purple,
|
||||||
|
Colors.red,
|
||||||
|
Colors.teal,
|
||||||
|
Colors.pink,
|
||||||
|
Colors.indigo,
|
||||||
|
Colors.amber,
|
||||||
|
Colors.cyan,
|
||||||
|
Colors.lime,
|
||||||
|
Colors.deepOrange,
|
||||||
|
];
|
||||||
|
|
||||||
|
// If within predefined range, use those
|
||||||
|
if (index < predefinedColors.length) {
|
||||||
|
return predefinedColors[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise generate using HSL for infinite colors
|
||||||
|
final hue = (index * 137.5) % 360; // Golden angle for distribution
|
||||||
|
return HSLColor.fromAHSL(1.0, hue, 0.6, 0.5).toColor();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> getProductivityDashBrdList(id) async {
|
Future<void> getProductivityDashBrdList(id) async {
|
||||||
// print('getClaimList called MagId - $managerId - $role');
|
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
});
|
});
|
||||||
// dynamic id = widget.policyNumber;
|
|
||||||
print('getProductivityDshID - $id');
|
|
||||||
try {
|
try {
|
||||||
final response = await apiService.findProductivityDashboardData(
|
final response = await apiService.findProductivityDashboardData(
|
||||||
id,
|
id,
|
||||||
SelctdProductivityproduct,
|
SelctdProductivityproduct,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response['status'] == 'success') {
|
if (response['status'] != 'success') {
|
||||||
final data = response['data'];
|
|
||||||
print('getProductivityDshBdData - ${response['data']}');
|
|
||||||
setState(() {
|
setState(() {
|
||||||
if (data is Map<String, dynamic>) {
|
isLoading = false;
|
||||||
staffLabels.clear();
|
|
||||||
staffChartData.clear();
|
|
||||||
maxPremium = 0;
|
|
||||||
|
|
||||||
final staffWise = (data['StaffWise'] ?? []) as List<dynamic>;
|
|
||||||
|
|
||||||
staffLabels.clear();
|
|
||||||
staffChartData.clear();
|
|
||||||
maxPremium = 0.0;
|
|
||||||
|
|
||||||
double _toDouble(dynamic v) {
|
|
||||||
if (v == null) return 0.0;
|
|
||||||
if (v is double) return v;
|
|
||||||
if (v is int) return v.toDouble();
|
|
||||||
return double.tryParse(v.toString()) ?? 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var staff in staffWise) {
|
|
||||||
final name = staff['sales_executive_name']?.toString() ?? '';
|
|
||||||
staffLabels.add(name);
|
|
||||||
|
|
||||||
double totalPre = 0.0;
|
|
||||||
double totalCur = 0.0;
|
|
||||||
|
|
||||||
final products = (staff['products_list'] ?? []) as List<dynamic>;
|
|
||||||
for (var p in products) {
|
|
||||||
totalPre += _toDouble(p['total_premium_pre_month']);
|
|
||||||
totalCur += _toDouble(p['total_premium_current_month']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// build 3 stacks: preMonth, currentMonth (stacked after pre), extra (difference optional)
|
|
||||||
final preStart = 0.0;
|
|
||||||
final preEnd = totalPre;
|
|
||||||
final curStart = preEnd;
|
|
||||||
final curEnd = preEnd + totalCur;
|
|
||||||
// optional extra stack (here zero, but kept for structure)
|
|
||||||
final extraStart = curEnd;
|
|
||||||
final extraEnd = curEnd; // no extra by default
|
|
||||||
|
|
||||||
// update chart max
|
|
||||||
maxPremium = [maxPremium, curEnd].reduce((a, b) => a > b ? a : b);
|
|
||||||
|
|
||||||
staffChartData.add([
|
|
||||||
[preStart, preEnd, Colors.cyan],
|
|
||||||
[curStart, curEnd, Colors.blueAccent],
|
|
||||||
// include extra only if needed >0
|
|
||||||
if ((extraEnd - extraStart) > 0)
|
|
||||||
[extraStart, extraEnd, Colors.grey],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// use setState to save and pass to chart
|
|
||||||
setState(() {
|
|
||||||
originalStaffWise = List.from(staffWise); // if you need
|
|
||||||
staffLabels = staffLabels;
|
|
||||||
staffChartData = staffChartData;
|
|
||||||
// choose a little padding for maxY
|
|
||||||
final chartMax = (maxPremium * 1.1).ceilToDouble();
|
|
||||||
// store chartMax somewhere e.g. chartMaxY
|
|
||||||
});
|
|
||||||
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (data is List) {
|
|
||||||
// // Already a list of maps
|
|
||||||
// getProductivityDshBdData = List<Map<String, dynamic>>.from(data);
|
|
||||||
// } else if (data is Map) {
|
|
||||||
// // Single object, wrap in a list
|
|
||||||
// getProductivityDshBdData = [Map<String, dynamic>.from(data)];
|
|
||||||
// } else {
|
|
||||||
// getProductivityDshBdData = [];
|
|
||||||
// }
|
|
||||||
// // getProductivityDshBdData = List<Map<String, dynamic>>.from(response['data']);
|
|
||||||
// originalData = getProductivityDshBdData;
|
|
||||||
// filteredData = List.from(originalData);
|
|
||||||
// // print('originalData - $getClaimPolicies');
|
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
if (data is Map<String, dynamic>) {
|
|
||||||
setState(() {
|
|
||||||
// Store BrokerWise
|
|
||||||
productWise = List<Map<String, dynamic>>.from(
|
|
||||||
data['productWise'] ?? [],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Store ProductWise
|
|
||||||
productWise = List<Map<String, dynamic>>.from(
|
|
||||||
data['productWise'] ?? [],
|
|
||||||
);
|
|
||||||
|
|
||||||
print('productWise - ${productWise}');
|
|
||||||
originalProductWise = List.from(productWise);
|
|
||||||
filteredProductWise = List.from(productWise);
|
|
||||||
|
|
||||||
// Store StaffWise
|
|
||||||
insurerWise = List<Map<String, dynamic>>.from(
|
|
||||||
data['insurerWise'] ?? [],
|
|
||||||
);
|
|
||||||
print('insurerWise - ${insurerWise}');
|
|
||||||
originalStaffWise = List.from(insurerWise);
|
|
||||||
filteredStaffWise = List.from(insurerWise);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// fallback
|
|
||||||
productWise = [];
|
|
||||||
productWise = [];
|
|
||||||
insurerWise = [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getProductivityDshBdData = [];
|
|
||||||
originalData = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final data = response['data'];
|
||||||
|
final staffWise = (data['StaffWise'] ?? []) as List<dynamic>;
|
||||||
|
|
||||||
|
print('data - $data');
|
||||||
|
print('staffWise - $staffWise');
|
||||||
|
|
||||||
|
// 🎨 STEP 1: Collect ALL unique vehicle types across all staff
|
||||||
|
Set<String> allVehicleTypes = {};
|
||||||
|
for (var staff in staffWise) {
|
||||||
|
final products = (staff['products_list'] ?? []) as List<dynamic>;
|
||||||
|
for (var p in products) {
|
||||||
|
final vehicleType = p['vechile_type']?.toString() ?? 'Unknown';
|
||||||
|
allVehicleTypes.add(vehicleType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🎨 STEP 2: Generate dynamic colors for all vehicle types
|
||||||
|
Map<String, Color> dynamicVehicleColors = {};
|
||||||
|
int colorIndex = 0;
|
||||||
|
for (var vehicleType in allVehicleTypes) {
|
||||||
|
dynamicVehicleColors[vehicleType] = _generateColorForVehicle(
|
||||||
|
vehicleType,
|
||||||
|
colorIndex++,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
print('Dynamic Vehicle Colors: $dynamicVehicleColors');
|
||||||
|
|
||||||
|
List<String> newLabels = [];
|
||||||
|
List<List<List<dynamic>>> newChartData = [];
|
||||||
|
List<List<String>> vehicleNames = [];
|
||||||
|
double newMax = 0.0;
|
||||||
|
|
||||||
|
double _toDouble(dynamic v) {
|
||||||
|
if (v == null) return 0.0;
|
||||||
|
if (v is double) return v;
|
||||||
|
if (v is int) return v.toDouble();
|
||||||
|
return double.tryParse(v.toString()) ?? 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var staff in staffWise) {
|
||||||
|
final name =
|
||||||
|
(staff['sales_executive_name'] ?? staff['short_name'])
|
||||||
|
?.toString() ??
|
||||||
|
'';
|
||||||
|
newLabels.add(name);
|
||||||
|
|
||||||
|
final products = (staff['products_list'] ?? []) as List<dynamic>;
|
||||||
|
|
||||||
|
List<List<dynamic>> currentRod = [];
|
||||||
|
List<List<dynamic>> previousRod = [];
|
||||||
|
List<String> staffVehicleNames = [];
|
||||||
|
|
||||||
|
double curStart = 0.0;
|
||||||
|
double preStart = 0.0;
|
||||||
|
|
||||||
|
for (var p in products) {
|
||||||
|
final cur = isInsureWisePolicy
|
||||||
|
? _toDouble(p['total_policies_current_month'])
|
||||||
|
: _toDouble(p['total_premium_current_month']);
|
||||||
|
final pre = isInsureWisePolicy
|
||||||
|
? _toDouble(p['total_policies_pre_month'])
|
||||||
|
: _toDouble(p['total_premium_pre_month']);
|
||||||
|
|
||||||
|
// Get vehicle type and its DYNAMIC color
|
||||||
|
final vehicleType = p['vechile_type']?.toString() ?? 'Unknown';
|
||||||
|
final color = dynamicVehicleColors[vehicleType] ?? Colors.grey;
|
||||||
|
|
||||||
|
staffVehicleNames.add(vehicleType);
|
||||||
|
|
||||||
|
// Add to current month rod with vehicle-specific color
|
||||||
|
currentRod.add([curStart, curStart + cur, color]);
|
||||||
|
curStart += cur;
|
||||||
|
|
||||||
|
// Add to previous month rod with lighter shade (60% opacity)
|
||||||
|
previousRod.add([preStart, preStart + pre, color.withOpacity(0.6)]);
|
||||||
|
preStart += pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
newChartData.add([currentRod, previousRod]);
|
||||||
|
vehicleNames.add(staffVehicleNames);
|
||||||
|
newMax = [newMax, curStart, preStart].reduce((a, b) => a > b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
originalStaffWise = staffWise
|
||||||
|
.map((e) => Map<String, dynamic>.from(e))
|
||||||
|
.toList();
|
||||||
|
filteredStaffWise = List<Map<String, dynamic>>.from(originalStaffWise);
|
||||||
|
|
||||||
|
staffLabels = newLabels;
|
||||||
|
staffChartData = newChartData;
|
||||||
|
staffVehicleTypeNames = vehicleNames;
|
||||||
|
vehicleColors = dynamicVehicleColors; // Save for legend
|
||||||
|
maxPremium = newMax;
|
||||||
|
|
||||||
|
productWise = List<Map<String, dynamic>>.from(
|
||||||
|
data['productWise'] ?? [],
|
||||||
|
);
|
||||||
|
insurerWise = List<Map<String, dynamic>>.from(
|
||||||
|
data['insurerWise'] ?? [],
|
||||||
|
);
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
@ -214,6 +253,31 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> buildStaffLabels() {
|
||||||
|
return filteredStaffWise.map<String>((item) {
|
||||||
|
final name = item['sales_executive_name'] ?? item['short_name'];
|
||||||
|
if (name != null && name.toString().trim().isNotEmpty) {
|
||||||
|
return name.toString();
|
||||||
|
} else {
|
||||||
|
return item['sales_executive_name']?.toString() ?? '';
|
||||||
|
}
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> convertToProductList(List<dynamic> rawList) {
|
||||||
|
return rawList.map<Map<String, dynamic>>((item) {
|
||||||
|
return {
|
||||||
|
"vehicle_type": item[0],
|
||||||
|
"current_month": double.tryParse(item[1].toString()) ?? 0.0,
|
||||||
|
"previous_month": double.tryParse(item[2].toString()) ?? 0.0,
|
||||||
|
};
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// In insurerContainer() you are passing staffLabels (which we now populate).
|
||||||
|
// Also set the chart maxY to some headroom:
|
||||||
|
// CustomStackedBarChart(..., maxY: (maxPremium * 1.1).ceilToDouble(), ...)
|
||||||
|
|
||||||
List<BarData> buildStaffBarData() {
|
List<BarData> buildStaffBarData() {
|
||||||
double parseDouble(dynamic value) {
|
double parseDouble(dynamic value) {
|
||||||
if (value == null) return 0.0;
|
if (value == null) return 0.0;
|
||||||
@ -241,17 +305,6 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> buildStaffLabels() {
|
|
||||||
return filteredStaffWise.map<String>((item) {
|
|
||||||
final name = item['short_name'];
|
|
||||||
if (name != null && name.toString().trim().isNotEmpty) {
|
|
||||||
return name.toString();
|
|
||||||
} else {
|
|
||||||
return item['short_name']?.toString() ?? '';
|
|
||||||
}
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BarData> buildProductBarData() {
|
List<BarData> buildProductBarData() {
|
||||||
double parseDouble(dynamic value) {
|
double parseDouble(dynamic value) {
|
||||||
if (value == null) return 0.0;
|
if (value == null) return 0.0;
|
||||||
@ -297,52 +350,53 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
// color: Colors.amber.shade100,
|
// color: Colors.amber.shade100,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
// Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
// children: [
|
||||||
Text('Hide and Show Charts : ', style: _styleSmall1),
|
// Text('Hide and Show Charts : ', style: _styleSmall1),
|
||||||
|
//
|
||||||
Row(
|
// Row(
|
||||||
children: [
|
// children: [
|
||||||
Transform.scale(
|
// Transform.scale(
|
||||||
scale: 0.75,
|
// scale: 0.75,
|
||||||
child: Checkbox(
|
// child: Checkbox(
|
||||||
value: showStaff,
|
// value: showStaff,
|
||||||
onChanged: (val) {
|
// onChanged: (val) {
|
||||||
setState(() => showStaff = val!);
|
// setState(() => showStaff = val!);
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Text(
|
// Text(
|
||||||
// showStaff ? "Staff" : "Staff Hidden",
|
// // showStaff ? "Staff" : "Staff Hidden",
|
||||||
"Staff",
|
// "Staff",
|
||||||
style: _styleSmall2,
|
// style: _styleSmall2,
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
|
//
|
||||||
// SizedBox(width: 10),
|
// // SizedBox(width: 10),
|
||||||
//
|
// //
|
||||||
// Row(
|
// // Row(
|
||||||
// children: [
|
// // children: [
|
||||||
// Transform.scale(
|
// // Transform.scale(
|
||||||
// scale: 0.75,
|
// // scale: 0.75,
|
||||||
// child: Checkbox(
|
// // child: Checkbox(
|
||||||
// value: showProduct,
|
// // value: showProduct,
|
||||||
// onChanged: (val) {
|
// // onChanged: (val) {
|
||||||
// setState(() => showProduct = val!);
|
// // setState(() => showProduct = val!);
|
||||||
// },
|
// // },
|
||||||
// ),
|
// // ),
|
||||||
// ),
|
// // ),
|
||||||
// Text(
|
// // Text(
|
||||||
// // showBroker ? "Broker" : "Broker Hidden",
|
// // // showBroker ? "Broker" : "Broker Hidden",
|
||||||
// "Product",
|
// // "Product",
|
||||||
// style: _styleSmall2,
|
// // style: _styleSmall2,
|
||||||
// ),
|
// // ),
|
||||||
// ],
|
// // ],
|
||||||
// ),
|
// // ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -361,8 +415,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
Widget insurerContainer() {
|
Widget insurerContainer() {
|
||||||
final chartStaffData = buildStaffBarData();
|
final chartStaffData = buildStaffBarData();
|
||||||
final chartStaffLabels = buildStaffLabels();
|
final chartStaffLabels = buildStaffLabels();
|
||||||
print('chartStaffData - $chartStaffData');
|
|
||||||
print('chartStaffLabels - $chartStaffLabels');
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.all(10),
|
||||||
margin: EdgeInsets.only(right: 20),
|
margin: EdgeInsets.only(right: 20),
|
||||||
@ -378,7 +431,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Staff Wise (Previous / Current Month)',
|
'Sales Executive Product Wise (Previous / Current Month)',
|
||||||
style: _chartHeader,
|
style: _chartHeader,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -390,99 +443,119 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
|||||||
scale: 0.5,
|
scale: 0.5,
|
||||||
child: Switch(
|
child: Switch(
|
||||||
value: isInsureWisePolicy,
|
value: isInsureWisePolicy,
|
||||||
onChanged: (val) => setState(() => isInsureWisePolicy = val),
|
onChanged: (val) {
|
||||||
|
setState(() {
|
||||||
|
isInsureWisePolicy = val;
|
||||||
|
});
|
||||||
|
// 👇 ADD THIS: Rebuild chart data with new toggle value
|
||||||
|
getProductivityDashBrdList(managerId);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
|
|
||||||
// Expanded(
|
|
||||||
// child: Container(
|
|
||||||
// clipBehavior: Clip.none,
|
|
||||||
// // color: Colors.red.shade100,
|
|
||||||
// child: CustomStackedBarChart(
|
|
||||||
// labels: staffLabels, // 👈 staff names
|
|
||||||
// maxY: maxPremium + 5000, // avoid touching border
|
|
||||||
// data: staffChartData,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomStackedBarChart(
|
child: CustomStackedBarChart(
|
||||||
labels: staffLabels,
|
labels: staffLabels,
|
||||||
data: staffChartData,
|
// maxY: (maxPremium * 1.1).ceilToDouble(),
|
||||||
maxY: (maxPremium * 1.1).ceilToDouble(), // a bit of headroom
|
maxY: _getSmartMaxValue(),
|
||||||
initialRotation: 1,
|
initialRotation: 1,
|
||||||
|
dataList: [],
|
||||||
|
productsList: staffChartData,
|
||||||
|
vehicleTypeNames:
|
||||||
|
staffVehicleTypeNames, // 👈 NEW: Pass vehicle names
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Row(children: [Expanded(child: legendWidget())]),
|
||||||
legendWidget(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget productContainer() {
|
// Widget productContainer() {
|
||||||
final chartProductData = buildProductBarData();
|
// final chartProductData = buildProductBarData();
|
||||||
final chartProductLabels = buildProductLabels();
|
// final chartProductLabels = buildProductLabels();
|
||||||
print('chartProductData - $chartProductData');
|
// print('chartProductData - $chartProductData');
|
||||||
print('chartProductLabels - $chartProductLabels');
|
// print('chartProductLabels - $chartProductLabels');
|
||||||
return Container(
|
// return Container(
|
||||||
padding: EdgeInsets.all(10),
|
// padding: EdgeInsets.all(10),
|
||||||
margin: EdgeInsets.only(right: 20),
|
// margin: EdgeInsets.only(right: 20),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(10),
|
// borderRadius: BorderRadius.circular(10),
|
||||||
),
|
// ),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
Row(
|
// Row(
|
||||||
children: [
|
// children: [
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: Text(
|
// child: Text(
|
||||||
'Staff Product Wise (Previous / Current Month)',
|
// 'Sales Executive Product Wise (Previous / Current Month)',
|
||||||
style: _chartHeader,
|
// style: _chartHeader,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Text(
|
// Text(
|
||||||
isProductWisePolicy ? "Policies" : "Premium",
|
// isProductWisePolicy ? "Policies" : "Premium",
|
||||||
style: _styleSmall1,
|
// style: _styleSmall1,
|
||||||
),
|
// ),
|
||||||
Transform.scale(
|
// Transform.scale(
|
||||||
scale: 0.5,
|
// scale: 0.5,
|
||||||
child: Switch(
|
// child: Switch(
|
||||||
value: isProductWisePolicy,
|
// value: isProductWisePolicy,
|
||||||
onChanged: (val) => setState(() => isProductWisePolicy = val),
|
// onChanged: (val) => setState(() => isProductWisePolicy = val),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: CustomBarChart(
|
// child: CustomBarChart(
|
||||||
dataList: chartProductData,
|
// dataList: chartProductData,
|
||||||
labels: chartProductLabels,
|
// labels: chartProductLabels,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
legendWidget(),
|
// legendWidget(),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
Widget legendWidget() {
|
Widget legendWidget() {
|
||||||
return Row(
|
return Wrap(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
spacing: 8,
|
||||||
|
runSpacing: 5,
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.circle, size: 10, color: Colors.cyan.shade300),
|
// Vehicle type legends (dynamically generated)
|
||||||
SizedBox(width: 2),
|
...vehicleColors.entries.map((entry) {
|
||||||
Text('Current Month', style: _styleSmall1),
|
return _legendItem(entry.key, entry.value);
|
||||||
SizedBox(width: 5),
|
}),
|
||||||
Icon(Icons.circle, size: 10, color: Colors.orange.shade300),
|
|
||||||
SizedBox(width: 2),
|
// Separator
|
||||||
Text('Previous Month', style: _styleSmall1),
|
SizedBox(width: 10),
|
||||||
|
Container(height: 12, width: 1, color: Colors.grey.shade300),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
|
||||||
|
// // Month legends
|
||||||
|
// _legendItem('Current (Solid)', Colors.black87),
|
||||||
|
// _legendItem('Previous (Light)', Colors.black38),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _legendItem(String label, Color color) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Text(label, style: _styleSmall1),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -639,6 +639,7 @@ class CreateProposal_QuickFormState
|
|||||||
print("Response: ${response.body}");
|
print("Response: ${response.body}");
|
||||||
// ToastHelper.showErrorToast(context, 'Proposal Created');
|
// ToastHelper.showErrorToast(context, 'Proposal Created');
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
getQuickQuotationList(managerId);
|
getQuickQuotationList(managerId);
|
||||||
// Navigator.of(context).pop();
|
// Navigator.of(context).pop();
|
||||||
} else if (response.statusCode == 403) {
|
} else if (response.statusCode == 403) {
|
||||||
@ -699,7 +700,8 @@ class CreateProposal_QuickFormState
|
|||||||
print("tre1");
|
print("tre1");
|
||||||
selectedId = null; // just update field
|
selectedId = null; // just update field
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setString('QuoteKeyProvider', 'fromQuickQuote');
|
||||||
context.go('/enquiryForStaff');
|
context.go('/enquiryForStaff');
|
||||||
print("tre11");
|
print("tre11");
|
||||||
getQuickQuotationList(managerId);
|
getQuickQuotationList(managerId);
|
||||||
|
|||||||
@ -59,6 +59,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
dynamic idPrimary;
|
dynamic idPrimary;
|
||||||
dynamic managerId;
|
dynamic managerId;
|
||||||
dynamic dashboardKey;
|
dynamic dashboardKey;
|
||||||
|
dynamic quickQuotationKey;
|
||||||
dynamic SelectedStatus;
|
dynamic SelectedStatus;
|
||||||
dynamic SelectedStaffId;
|
dynamic SelectedStaffId;
|
||||||
String? selectedFileNames;
|
String? selectedFileNames;
|
||||||
@ -79,6 +80,14 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
List<Map<String, dynamic>> originalData = [];
|
List<Map<String, dynamic>> originalData = [];
|
||||||
List<Map<String, dynamic>> filteredData = [];
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
|
bool isLoadingInsurers = false;
|
||||||
|
bool isLoadingInsuranceType = false;
|
||||||
|
bool isLoadingBroker = false;
|
||||||
|
bool isLoadingPaymentMode = false;
|
||||||
|
bool isLoadingStaffEnqAssign = false;
|
||||||
|
bool isLoadingStaffList = false;
|
||||||
|
bool isLoadingVehicleType = false;
|
||||||
|
bool isLoadingAgentList = false;
|
||||||
dynamic roleId;
|
dynamic roleId;
|
||||||
bool _showFilterRow = false;
|
bool _showFilterRow = false;
|
||||||
|
|
||||||
@ -139,6 +148,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
|
|
||||||
String? selectedId;
|
String? selectedId;
|
||||||
|
|
||||||
|
// int selectedIndex = 1;
|
||||||
int selectedIndex = 0;
|
int selectedIndex = 0;
|
||||||
int autoRefreshIndex = 0;
|
int autoRefreshIndex = 0;
|
||||||
|
|
||||||
@ -238,11 +248,17 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
dashboardKey = prefs.getString('dashboardKeyProvider');
|
dashboardKey = prefs.getString('dashboardKeyProvider');
|
||||||
|
quickQuotationKey = prefs.getString('QuoteKeyProvider');
|
||||||
final dashboardStatus = prefs.getString('dashboardStatusProvider');
|
final dashboardStatus = prefs.getString('dashboardStatusProvider');
|
||||||
final dashboardStaffId = prefs.getString('dashboardStaffIdProvider');
|
final dashboardStaffId = prefs.getString('dashboardStaffIdProvider');
|
||||||
|
|
||||||
print('handlerIdENQ - $handlerId');
|
print('handlerIdENQ - $handlerId');
|
||||||
print("C72 => r : $roleId | uId: $userId !mID : $managerId ");
|
print("C72 => r : $roleId | uId: $userId !mID : $managerId ");
|
||||||
|
print('quickQuotationKey');
|
||||||
|
if (quickQuotationKey == 'fromQuickQuote') {
|
||||||
|
print('quickQuotationKey - $quickQuotationKey');
|
||||||
|
callRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
print('dashboardKey - $dashboardKey');
|
print('dashboardKey - $dashboardKey');
|
||||||
print('dashboardStatus - $dashboardStatus');
|
print('dashboardStatus - $dashboardStatus');
|
||||||
@ -421,7 +437,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getInsurers() async {
|
Future<void> getInsurers() async {
|
||||||
print('Insurers called');
|
print('Insurers called');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingInsurers = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -444,7 +460,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingInsurers = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,7 +468,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getInsuranceType() async {
|
Future<void> getInsuranceType() async {
|
||||||
print('getClaimList called');
|
print('getClaimList called');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingInsuranceType = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -477,7 +493,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingInsuranceType = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -485,7 +501,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getBroker() async {
|
Future<void> getBroker() async {
|
||||||
print('getBroker called');
|
print('getBroker called');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingBroker = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -508,7 +524,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingBroker = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,7 +532,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getPaymentMode() async {
|
Future<void> getPaymentMode() async {
|
||||||
print('getPaymentMode called');
|
print('getPaymentMode called');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingPaymentMode = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -541,7 +557,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingPaymentMode = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -549,7 +565,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getStaffDetailsForEnquiryAssignment(int id) async {
|
Future<void> getStaffDetailsForEnquiryAssignment(int id) async {
|
||||||
print('getStaffDetailsForEnquiryAssignment called By handler');
|
print('getStaffDetailsForEnquiryAssignment called By handler');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingStaffEnqAssign = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -578,7 +594,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingStaffEnqAssign = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,7 +609,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
}) async {
|
}) async {
|
||||||
print('DAJJshA72 => Fns called => $managerId | $role');
|
print('DAJJshA72 => Fns called => $managerId | $role');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingStaffList = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
dynamic fromDt;
|
dynamic fromDt;
|
||||||
@ -612,7 +628,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
|
|
||||||
final yesterday = today.subtract(Duration(days: 1));
|
final yesterday = today.subtract(Duration(days: 1));
|
||||||
|
|
||||||
fromDt = dateFormat.format(yesterday.subtract(Duration(days: 5)));
|
fromDt = dateFormat.format(yesterday.subtract(Duration(days: 2)));
|
||||||
toDt = dateFormat.format(yesterday);
|
toDt = dateFormat.format(yesterday);
|
||||||
|
|
||||||
print('PrevPending FROM TO - $fromDt - $toDt');
|
print('PrevPending FROM TO - $fromDt - $toDt');
|
||||||
@ -635,7 +651,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print("ENQ LIST PAGE");
|
print("ENQ LIST PAGE");
|
||||||
|
|
||||||
final today = DateTime.now();
|
final today = DateTime.now();
|
||||||
fromDt = dateFormat.format(today.subtract(Duration(days: 5)));
|
fromDt = dateFormat.format(today.subtract(Duration(days: 2)));
|
||||||
// fromDt = dateFormat.format(today);
|
// fromDt = dateFormat.format(today);
|
||||||
toDt = dateFormat.format(today);
|
toDt = dateFormat.format(today);
|
||||||
|
|
||||||
@ -694,13 +710,13 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('ToDate : $toDate');
|
print('ToDate : $toDate');
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
if (SelectedStatus == 'Completed' || autoRefreshIndex == 1) {
|
// if (SelectedStatus == 'Completed' || autoRefreshIndex == 1) {
|
||||||
selectedIndex = 1;
|
// selectedIndex = 1;
|
||||||
SelectedStatus = 'Completed';
|
// SelectedStatus = 'Completed';
|
||||||
} else {
|
// } else {
|
||||||
selectedIndex = 0;
|
// selectedIndex = 0;
|
||||||
SelectedStatus = 'OtherThenCompleted';
|
// SelectedStatus = 'OtherThenCompleted';
|
||||||
}
|
// }
|
||||||
controllers['startDate']?.text = fromDate;
|
controllers['startDate']?.text = fromDate;
|
||||||
controllers['endDate']?.text = toDate;
|
controllers['endDate']?.text = toDate;
|
||||||
if (data is List) {
|
if (data is List) {
|
||||||
@ -721,7 +737,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingStaffList = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1516,7 +1532,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getVehicleType() async {
|
Future<void> getVehicleType() async {
|
||||||
print('getClaimList called');
|
print('getClaimList called');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingVehicleType = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1541,7 +1557,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingVehicleType = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1549,7 +1565,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Future<void> getAgentList(id) async {
|
Future<void> getAgentList(id) async {
|
||||||
print('getAgentListData called');
|
print('getAgentListData called');
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = true;
|
isLoadingAgentList = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -1573,7 +1589,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print('Exception occurred: $e');
|
print('Exception occurred: $e');
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoadingAgentList = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3472,7 +3488,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
"created_on",
|
"created_on",
|
||||||
"agent_name",
|
"agent_name",
|
||||||
"assigned_to_name",
|
"assigned_to_name",
|
||||||
"insurer_name",
|
"insurer_short_name",
|
||||||
"reg_no",
|
"reg_no",
|
||||||
"insured_name",
|
"insured_name",
|
||||||
"updated_on",
|
"updated_on",
|
||||||
@ -4003,6 +4019,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
item['insurer_short_name'] != null
|
item['insurer_short_name'] != null
|
||||||
? item['insurer_short_name']
|
? item['insurer_short_name']
|
||||||
: '-',
|
: '-',
|
||||||
|
|
||||||
style: _dataBoldthm2,
|
style: _dataBoldthm2,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -4012,6 +4029,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
item['broker_name'] != null
|
item['broker_name'] != null
|
||||||
? _truncateText(item['broker_name'], 8)
|
? _truncateText(item['broker_name'], 8)
|
||||||
: '-',
|
: '-',
|
||||||
|
|
||||||
style: _dataBoldthm4,
|
style: _dataBoldthm4,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -4267,40 +4285,40 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
Material(
|
Material(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: null,
|
// onTap: null,
|
||||||
// hoverColor: Color(0xFFEAF6F4),
|
hoverColor: Color(0xFFEAF6F4),
|
||||||
// onTap: (item['enquiry_status'] == 'Completed')
|
onTap: (item['enquiry_status'] == 'Completed')
|
||||||
// ? () async {
|
? () async {
|
||||||
// final prefs =
|
final prefs =
|
||||||
// await SharedPreferences.getInstance();
|
await SharedPreferences.getInstance();
|
||||||
//
|
|
||||||
// // ✅ Remove old value (if any)
|
// ✅ Remove old value (if any)
|
||||||
// await prefs.remove('enqStaffDataId');
|
await prefs.remove('enqStaffDataId');
|
||||||
//
|
|
||||||
// // ✅ Save the new id
|
// ✅ Save the new id
|
||||||
// await prefs.setString(
|
await prefs.setString(
|
||||||
// 'enqStaffDataId',
|
'enqStaffDataId',
|
||||||
// id.toString(),
|
id.toString(),
|
||||||
// );
|
);
|
||||||
//
|
|
||||||
// // Read it back if needed
|
// Read it back if needed
|
||||||
// final dynamic? enqStaffDataId = prefs.getString(
|
final dynamic? enqStaffDataId = prefs.getString(
|
||||||
// 'enqStaffDataId',
|
'enqStaffDataId',
|
||||||
// );
|
);
|
||||||
//
|
|
||||||
// // ✅ Update provider too
|
// ✅ Update provider too
|
||||||
// ref
|
ref
|
||||||
// .read(quotationStaffIdProvider.notifier)
|
.read(quotationStaffIdProvider.notifier)
|
||||||
// .state =
|
.state =
|
||||||
// enqStaffDataId;
|
enqStaffDataId;
|
||||||
//
|
|
||||||
// buildPolicyCreatedStatusActions(
|
buildPolicyCreatedStatusActions(
|
||||||
// context,
|
context,
|
||||||
// status,
|
status,
|
||||||
// item['id'],
|
item['id'],
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
// : null,
|
: null,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(vertical: 2.0),
|
padding: EdgeInsets.symmetric(vertical: 2.0),
|
||||||
margin: EdgeInsets.symmetric(vertical: 2),
|
margin: EdgeInsets.symmetric(vertical: 2),
|
||||||
@ -4963,6 +4981,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
print(
|
print(
|
||||||
"❌ Cancel clicked. Ignoring old file.",
|
"❌ Cancel clicked. Ignoring old file.",
|
||||||
);
|
);
|
||||||
|
ToastHelper.showErrorToast(
|
||||||
|
context,
|
||||||
|
'Please upload a new file. No previous file exists.',
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
print('Clear Fields');
|
print('Clear Fields');
|
||||||
selectedFileNames =
|
selectedFileNames =
|
||||||
@ -5257,15 +5279,15 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
|
|
||||||
if (selectedIndex == '1') {
|
// if (selectedIndex == '1') {
|
||||||
getStaffList(
|
// getStaffList(
|
||||||
managerId,
|
// managerId,
|
||||||
roleId,
|
// roleId,
|
||||||
SelectedStatus: 'Completed',
|
// SelectedStatus: 'Completed',
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
getStaffList(managerId, roleId);
|
// getStaffList(managerId, roleId);
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
|
|||||||
@ -1,20 +1,38 @@
|
|||||||
|
// custom_stacked_bar_chart.dart
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../../data/models/bar_data.dart';
|
||||||
|
|
||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import 'appChartColors.dart';
|
||||||
|
|
||||||
class CustomStackedBarChart extends StatefulWidget {
|
class CustomStackedBarChart extends StatefulWidget {
|
||||||
final List<String> labels;
|
final List<String> labels;
|
||||||
final List<List<List<dynamic>>>
|
final List<dynamic> dataList;
|
||||||
data; // data[group][stackIndex] = [start, end, color]
|
|
||||||
final double maxY;
|
final double maxY;
|
||||||
final int initialRotation;
|
final int initialRotation;
|
||||||
|
final List<List<List<dynamic>>> productsList;
|
||||||
|
final List<List<String>>? vehicleTypeNames;
|
||||||
|
final Map<String, Color>? vehicleColorMap; // Dynamic color mapping
|
||||||
|
|
||||||
const CustomStackedBarChart({
|
const CustomStackedBarChart({
|
||||||
super.key,
|
super.key,
|
||||||
required this.labels,
|
required this.labels,
|
||||||
required this.data,
|
required this.dataList,
|
||||||
this.maxY = 100.0,
|
this.maxY = 100.0,
|
||||||
this.initialRotation = 1,
|
this.initialRotation = 1,
|
||||||
|
required this.productsList,
|
||||||
|
this.vehicleTypeNames,
|
||||||
|
this.vehicleColorMap,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -30,89 +48,50 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
|||||||
rotationTurns = widget.initialRotation;
|
rotationTurns = widget.initialRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
double _toDouble(dynamic v) {
|
|
||||||
if (v == null) return 0.0;
|
|
||||||
if (v is double) return v;
|
|
||||||
if (v is int) return v.toDouble();
|
|
||||||
return double.tryParse(v.toString()) ?? 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BarChartGroupData _generateGroup(int xIndex) {
|
|
||||||
// Each group is a single stacked rod (one staff)
|
|
||||||
final stacks = widget.data[xIndex];
|
|
||||||
final rodStackItems = <BarChartRodStackItem>[];
|
|
||||||
|
|
||||||
for (var s in stacks) {
|
|
||||||
// s expected: [start, end, color]
|
|
||||||
final start = _toDouble(s[0]);
|
|
||||||
final end = _toDouble(s[1]);
|
|
||||||
final color = (s.length > 2 && s[2] is Color)
|
|
||||||
? s[2] as Color
|
|
||||||
: Colors.grey;
|
|
||||||
rodStackItems.add(BarChartRodStackItem(start, end, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
final maxEnd = rodStackItems.isNotEmpty
|
|
||||||
? rodStackItems.map((r) => r.toY).reduce((a, b) => a > b ? a : b)
|
|
||||||
: 0.0;
|
|
||||||
|
|
||||||
return BarChartGroupData(
|
|
||||||
x: xIndex,
|
|
||||||
groupVertically: false,
|
|
||||||
barRods: [
|
|
||||||
BarChartRodData(
|
|
||||||
toY: maxEnd,
|
|
||||||
width: 12,
|
|
||||||
borderRadius: BorderRadius.zero,
|
|
||||||
rodStackItems: rodStackItems,
|
|
||||||
),
|
|
||||||
BarChartRodData(
|
|
||||||
toY: maxEnd,
|
|
||||||
width: 12,
|
|
||||||
borderRadius: BorderRadius.zero,
|
|
||||||
rodStackItems: rodStackItems,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final maxY = widget.maxY;
|
final maxY = widget.maxY <= 0 ? 100.0 : widget.maxY;
|
||||||
|
|
||||||
return AspectRatio(
|
return AspectRatio(
|
||||||
aspectRatio: 1.6,
|
aspectRatio: 1.6,
|
||||||
child: BarChart(
|
child: BarChart(
|
||||||
BarChartData(
|
BarChartData(
|
||||||
alignment: BarChartAlignment.center,
|
alignment: BarChartAlignment.spaceAround,
|
||||||
rotationQuarterTurns: rotationTurns,
|
rotationQuarterTurns: rotationTurns,
|
||||||
|
|
||||||
|
// gridData: FlGridData(
|
||||||
|
// show: true,
|
||||||
|
// checkToShowHorizontalLine: (value) {
|
||||||
|
// final step = maxY / 5;
|
||||||
|
// if (step == 0) return false;
|
||||||
|
// return (value % step).abs() < 0.0001;
|
||||||
|
// },
|
||||||
|
// getDrawingHorizontalLine: (value) =>
|
||||||
|
// FlLine(color: Colors.grey.withOpacity(0.12), strokeWidth: 0.8),
|
||||||
|
// drawVerticalLine: false,
|
||||||
|
//
|
||||||
|
// ),
|
||||||
gridData: FlGridData(
|
gridData: FlGridData(
|
||||||
show: true,
|
show: true,
|
||||||
checkToShowHorizontalLine: (value) => value % (maxY / 5) == 0,
|
// drawVerticalLine: true,
|
||||||
getDrawingHorizontalLine: (value) =>
|
|
||||||
FlLine(color: Colors.grey.withOpacity(0.12), strokeWidth: 0.8),
|
|
||||||
drawVerticalLine: false,
|
drawVerticalLine: false,
|
||||||
|
getDrawingHorizontalLine: (value) => FlLine(
|
||||||
|
// color: AppColors.gridLinesColor.withValues(alpha: 0.2),
|
||||||
|
color: Colors.blueGrey.shade100,
|
||||||
|
// color: Colors.black,
|
||||||
|
// color: AppColors.borderColor,
|
||||||
|
strokeWidth: 0.3,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
borderData: FlBorderData(show: false),
|
// borderData: FlBorderData(show: false),
|
||||||
barTouchData: BarTouchData(
|
borderData: FlBorderData(
|
||||||
enabled: true,
|
show: true,
|
||||||
touchTooltipData: BarTouchTooltipData(
|
border: Border(
|
||||||
tooltipRoundedRadius: 6,
|
bottom: BorderSide(
|
||||||
tooltipPadding: const EdgeInsets.symmetric(
|
color: AppColors.contentColorBlack,
|
||||||
horizontal: 8,
|
width: 0.1,
|
||||||
vertical: 6,
|
|
||||||
),
|
),
|
||||||
fitInsideHorizontally: true,
|
right: BorderSide(color: AppColors.contentColorBlack, width: 0.1),
|
||||||
fitInsideVertically: true,
|
|
||||||
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
|
||||||
return BarTooltipItem(
|
|
||||||
'${rod.toY.toStringAsFixed(2)}',
|
|
||||||
GoogleFonts.poppins(
|
|
||||||
color: Colors.black,
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
titlesData: FlTitlesData(
|
titlesData: FlTitlesData(
|
||||||
@ -122,8 +101,9 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
|||||||
reservedSize: 56,
|
reservedSize: 56,
|
||||||
getTitlesWidget: (value, meta) {
|
getTitlesWidget: (value, meta) {
|
||||||
final i = value.toInt();
|
final i = value.toInt();
|
||||||
if (i < 0 || i >= widget.labels.length)
|
if (i < 0 || i >= widget.labels.length) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
|
}
|
||||||
return SideTitleWidget(
|
return SideTitleWidget(
|
||||||
meta: meta,
|
meta: meta,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -141,11 +121,18 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
|||||||
rightTitles: AxisTitles(
|
rightTitles: AxisTitles(
|
||||||
sideTitles: SideTitles(
|
sideTitles: SideTitles(
|
||||||
showTitles: true,
|
showTitles: true,
|
||||||
reservedSize: 40,
|
reservedSize: 50,
|
||||||
getTitlesWidget: (value, meta) {
|
getTitlesWidget: (value, meta) {
|
||||||
return Text(
|
return Transform.rotate(
|
||||||
value.toInt().toString(),
|
angle: -3,
|
||||||
style: GoogleFonts.inter(fontSize: 9),
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 3.0),
|
||||||
|
child: Text(
|
||||||
|
value.toInt().toString(),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: GoogleFonts.inter(fontSize: 10),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -153,10 +140,115 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
|||||||
leftTitles: const AxisTitles(),
|
leftTitles: const AxisTitles(),
|
||||||
topTitles: const AxisTitles(),
|
topTitles: const AxisTitles(),
|
||||||
),
|
),
|
||||||
barGroups: List.generate(
|
barTouchData: BarTouchData(
|
||||||
widget.data.length,
|
enabled: true,
|
||||||
(i) => _generateGroup(i),
|
touchTooltipData: BarTouchTooltipData(
|
||||||
|
tooltipRoundedRadius: 8,
|
||||||
|
tooltipPadding: const EdgeInsets.all(8),
|
||||||
|
tooltipMargin: 8,
|
||||||
|
fitInsideHorizontally: true,
|
||||||
|
fitInsideVertically: true,
|
||||||
|
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||||
|
// Determine if this is current or previous month
|
||||||
|
final isCurrentMonth = rodIndex == 0;
|
||||||
|
final monthLabel = isCurrentMonth ? 'Current' : 'Previous';
|
||||||
|
|
||||||
|
// Calculate total for this rod
|
||||||
|
final total = rod.rodStackItems.isNotEmpty
|
||||||
|
? rod.rodStackItems
|
||||||
|
.map((s) => s.toY - s.fromY)
|
||||||
|
.reduce((a, b) => a + b)
|
||||||
|
: 0.0;
|
||||||
|
|
||||||
|
// Build detailed breakdown
|
||||||
|
String breakdown = '';
|
||||||
|
if (rod.rodStackItems.isNotEmpty) {
|
||||||
|
for (int i = 0; i < rod.rodStackItems.length; i++) {
|
||||||
|
final item = rod.rodStackItems[i];
|
||||||
|
final value = item.toY - item.fromY;
|
||||||
|
if (value > 0) {
|
||||||
|
// Try to get vehicle type name if provided
|
||||||
|
String vehicleName = 'Item ${i + 1}';
|
||||||
|
if (widget.vehicleTypeNames != null &&
|
||||||
|
groupIndex < widget.vehicleTypeNames!.length &&
|
||||||
|
i < widget.vehicleTypeNames![groupIndex].length) {
|
||||||
|
vehicleName = widget.vehicleTypeNames![groupIndex][i];
|
||||||
|
}
|
||||||
|
breakdown +=
|
||||||
|
'\n$vehicleName: ${value.toStringAsFixed(0)}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BarTooltipItem(
|
||||||
|
'$monthLabel Month\nTotal: ${total.toStringAsFixed(0)}$breakdown',
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
GoogleFonts.poppins(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
barGroups: widget.productsList.asMap().entries.map((entry) {
|
||||||
|
int x = entry.key;
|
||||||
|
List<List<dynamic>> rods = entry.value;
|
||||||
|
|
||||||
|
List<BarChartRodStackItem> currentStack = [];
|
||||||
|
List<BarChartRodStackItem> previousStack = [];
|
||||||
|
|
||||||
|
double cumCurrent = 0;
|
||||||
|
// double cumPrev = 25000;
|
||||||
|
double cumPrev = 0;
|
||||||
|
|
||||||
|
// Current month
|
||||||
|
for (var item in rods[0]) {
|
||||||
|
double value = (item[1] - item[0]).toDouble();
|
||||||
|
currentStack.add(
|
||||||
|
BarChartRodStackItem(
|
||||||
|
cumCurrent,
|
||||||
|
cumCurrent + value,
|
||||||
|
item[2] as Color? ?? Colors.grey,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
cumCurrent += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Previous month
|
||||||
|
for (var item in rods[1]) {
|
||||||
|
double value = (item[1] - item[0]).toDouble();
|
||||||
|
previousStack.add(
|
||||||
|
BarChartRodStackItem(
|
||||||
|
cumPrev,
|
||||||
|
cumPrev + value,
|
||||||
|
item[2] as Color? ?? Colors.grey,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
cumPrev += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BarChartGroupData(
|
||||||
|
x: x,
|
||||||
|
groupVertically: false,
|
||||||
|
barRods: [
|
||||||
|
BarChartRodData(
|
||||||
|
toY: cumCurrent,
|
||||||
|
width: 16,
|
||||||
|
rodStackItems: currentStack,
|
||||||
|
borderRadius: BorderRadius.zero,
|
||||||
|
),
|
||||||
|
BarChartRodData(
|
||||||
|
toY: cumPrev,
|
||||||
|
width: 16,
|
||||||
|
rodStackItems: previousStack,
|
||||||
|
borderRadius: BorderRadius.zero,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
maxY: maxY,
|
maxY: maxY,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user