merged policy validation
This commit is contained in:
commit
7a07b0f3bd
File diff suppressed because one or more lines are too long
@ -771,46 +771,15 @@ class ApiService {
|
||||
|
||||
// ----------------------------------- ENQUIRY -------------------------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> fetchEnquiryList1(int id, role) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
|
||||
final url;
|
||||
|
||||
if (role == 'manager') {
|
||||
url = Uri.parse(
|
||||
'${Env.apiUrl}enquiry/enquiryList?manager_id=$id&from_date=&to_date=',
|
||||
);
|
||||
} else if (role == 'staff') {
|
||||
url = Uri.parse(
|
||||
'${Env.apiUrl}enquiry/enquiryList?staff_id=$id&from_date=&to_date=',
|
||||
);
|
||||
} else {
|
||||
url = Uri.parse(
|
||||
'${Env.apiUrl}enquiry/enquiryList?agent_id=$id&from_date=&to_date=',
|
||||
);
|
||||
}
|
||||
// final url = Uri.parse(
|
||||
// 'https://venbait.in/nhance/partner/dev/api/agent/agentList?manager_id=${managerId}',
|
||||
// );
|
||||
final headers = {
|
||||
'Authorization': 'Bearer $_token' ?? '',
|
||||
'app-signature': Env.App_Signature,
|
||||
};
|
||||
final response = await _makeGetRequest(url, headers);
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> fetchEnquiryList(int managerid,
|
||||
int id,
|
||||
String role, {
|
||||
String? fromDate,
|
||||
String? toDate,
|
||||
String? selectedStatus,
|
||||
String? selectedStaffId,
|
||||
}) async {
|
||||
Future<Map<String, dynamic>> fetchEnquiryList(
|
||||
int managerid,
|
||||
int id,
|
||||
String role, {
|
||||
String? fromDate,
|
||||
String? toDate,
|
||||
String? selectedStatus,
|
||||
String? selectedStaffId,
|
||||
}) async {
|
||||
print("selectedStatusselectedStatus - $selectedStatus");
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
@ -1166,23 +1135,67 @@ class ApiService {
|
||||
|
||||
// ----------------------------------- CLAIMS -------------------------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> fetchClaimList(int id, role) async {
|
||||
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(
|
||||
managerId,
|
||||
int userId,
|
||||
role,
|
||||
) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
|
||||
final userId = '1';
|
||||
final url;
|
||||
|
||||
if (role == 'manager') {
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?manager_id=$id');
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?manager_id=$managerId');
|
||||
} else if (role == 'agent') {
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?agent_id=$id');
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?agent_id=$userId');
|
||||
} else if (role == 'handler') {
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?handler_id=$id');
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?handler_id=$userId');
|
||||
} else {
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?staff_id=$id');
|
||||
url = Uri.parse('${Env.apiUrl}claim/ClaimList?staff_id=$userId');
|
||||
}
|
||||
|
||||
// final url = Uri.parse(
|
||||
@ -1213,18 +1226,21 @@ class ApiService {
|
||||
|
||||
// ----------------------------------- ENDORSEMENT -------------------------------------------------
|
||||
|
||||
Future<Map<String, dynamic>> fetchEndorsementList(int id, role) async {
|
||||
Future<Map<String, dynamic>> fetchEndorsementList(
|
||||
managerId,
|
||||
int id,
|
||||
role,
|
||||
) async {
|
||||
// print(_token);
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
}
|
||||
|
||||
final userId = '1';
|
||||
final url;
|
||||
|
||||
if (role == 'manager') {
|
||||
url = Uri.parse(
|
||||
'${Env.apiUrl}endorsement/endorsementList?manager_id=$id',
|
||||
'${Env.apiUrl}endorsement/endorsementList?manager_id=$managerId',
|
||||
);
|
||||
} else if (role == 'agent') {
|
||||
url = Uri.parse('${Env.apiUrl}endorsement/endorsementList?agent_id=$id');
|
||||
@ -1323,8 +1339,11 @@ class ApiService {
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> fetchStaffListForEnquiryAssignDropDown(id,
|
||||
role,) async {
|
||||
Future<Map<String, dynamic>> fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
role,
|
||||
) async {
|
||||
print('fetchHandlerNameDropDown');
|
||||
if (_token == null) {
|
||||
await _initializeToken();
|
||||
@ -1335,7 +1354,7 @@ class ApiService {
|
||||
|
||||
if (role == 'manager') {
|
||||
url = Uri.parse(
|
||||
'${Env.apiUrl}staff/staffListForEnquiryAssignDropdown?manager_id=$id',
|
||||
'${Env.apiUrl}staff/staffListForEnquiryAssignDropdown?manager_id=$managerId',
|
||||
);
|
||||
} else {
|
||||
url = Uri.parse(
|
||||
|
||||
@ -706,11 +706,11 @@ class _HoverableContainerState extends State<_HoverableContainer> {
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
size: 10,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
// Icon(
|
||||
// Icons.arrow_forward_ios_rounded,
|
||||
// size: 10,
|
||||
// color: Colors.grey.shade600,
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -16,3 +16,4 @@ final staffIndiviualAttendanceNameIdProvider = StateProvider<String?>(
|
||||
final dashboardKeyProvider = StateProvider<int?>((ref) => null);
|
||||
final dashboardStatusProvider = StateProvider<String?>((ref) => null);
|
||||
final dashboardStaffIdProvider = StateProvider<String?>((ref) => null);
|
||||
final enquiryRefreshProvider = StateProvider<bool>((ref) => false);
|
||||
|
||||
@ -26,7 +26,7 @@ class AddDialog extends StatefulWidget {
|
||||
final dynamic managerId;
|
||||
final dynamic role;
|
||||
final void Function(String value) onSubmit;
|
||||
final dynamic policyNumber;
|
||||
// final dynamic policyNumber;
|
||||
const AddDialog({
|
||||
super.key,
|
||||
required this.title,
|
||||
@ -34,7 +34,7 @@ class AddDialog extends StatefulWidget {
|
||||
required this.userId,
|
||||
required this.managerId,
|
||||
required this.role,
|
||||
this.policyNumber,
|
||||
// this.policyNumber,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -69,6 +69,10 @@ class _AddDialogState extends State<AddDialog> {
|
||||
|
||||
List<String> tabHeader = ['policyNum', 'claimsDesc', 'remarks'];
|
||||
|
||||
final TextEditingController _vehicleSearchController =
|
||||
TextEditingController();
|
||||
final TextEditingController _policySearchController = TextEditingController();
|
||||
|
||||
final TextEditingController _searchStaffController = TextEditingController();
|
||||
|
||||
List<Map<String, dynamic>> getClaimsTypeData = [];
|
||||
@ -86,6 +90,14 @@ class _AddDialogState extends State<AddDialog> {
|
||||
List<Map<String, dynamic>> originalData = [];
|
||||
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() {
|
||||
final data = {
|
||||
"policy_number": controllers["policyNum"]?.text,
|
||||
@ -116,7 +128,7 @@ class _AddDialogState extends State<AddDialog> {
|
||||
controllers[field] = TextEditingController();
|
||||
}
|
||||
|
||||
controllers["policyNum"]?.text = widget.policyNumber;
|
||||
// controllers["policyNum"]?.text = widget.policyNumber;
|
||||
print('userIFF - ${widget.userId}');
|
||||
print('roleIFF - ${widget.role}');
|
||||
|
||||
@ -136,6 +148,107 @@ class _AddDialogState extends State<AddDialog> {
|
||||
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(
|
||||
dynamic managerId,
|
||||
role, {
|
||||
@ -473,20 +586,160 @@ class _AddDialogState extends State<AddDialog> {
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
ThemedSearchField(
|
||||
hintText: 'Search',
|
||||
// backgroundColor: Color(0xFFF6F8F8),
|
||||
backgroundColor: Color(0xFFFFFFFF),
|
||||
txtHeight: 30,
|
||||
onChanged: filterData,
|
||||
controller: _searchStaffController,
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
// txtwidth: ResponsiveLayout.isMobile(context)
|
||||
// ? MediaQuery.of(context).size.width * 0.7
|
||||
// : MediaQuery.of(context).size.width * 0.15,
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
ThemedSearchField(
|
||||
hintText: 'Search By Vehicle Number',
|
||||
backgroundColor: Color(0xFFFFFFFF),
|
||||
txtHeight: 30,
|
||||
controller: _vehicleSearchController,
|
||||
onChanged: (val) async {
|
||||
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),
|
||||
|
||||
// 🔹 Switch content dynamically
|
||||
@ -519,10 +772,24 @@ class _AddDialogState extends State<AddDialog> {
|
||||
key: _formKeyClaims,
|
||||
child: Column(
|
||||
children: [
|
||||
buildClaimType(context),
|
||||
buildPolicyNumber(context),
|
||||
buildUploadDocumentClaims(context),
|
||||
buildClaimsDesc(context),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
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,
|
||||
child: Column(
|
||||
children: [
|
||||
buildEndrosType(context),
|
||||
buildUploadDocumentEndorsment(context),
|
||||
buildEndrosRemarks(context),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
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(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Policy Number", style: _textStyle),
|
||||
Text("Policy Number *", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
controller: controllers['policyNum']!,
|
||||
@ -566,11 +848,12 @@ class _AddDialogState extends State<AddDialog> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Claims Description *", style: _textStyle),
|
||||
SizedBox(height: 10),
|
||||
Text("Claims Description ", style: _textStyle),
|
||||
// SizedBox(height: 10),
|
||||
ThemedFormField(
|
||||
backgroundColor: Color(0xFFEDF6F5),
|
||||
controller: controllers['claimsDesc']!,
|
||||
txtheight: 45,
|
||||
validator: (value) => Validators.requiredField(value, "claimsDesc"),
|
||||
txtwidth: ResponsiveLayout.isMobile(context)
|
||||
? null
|
||||
@ -860,6 +1143,7 @@ class _AddDialogState extends State<AddDialog> {
|
||||
? null
|
||||
: MediaQuery.of(context).size.width * 0.26,
|
||||
keyboardType: TextInputType.multiline,
|
||||
txtheight: 45,
|
||||
),
|
||||
],
|
||||
);
|
||||
@ -952,4 +1236,8 @@ class _AddDialogState extends State<AddDialog> {
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
static final TextStyle _textStyle1 = TextStyle(
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w400,
|
||||
);
|
||||
}
|
||||
|
||||
@ -581,7 +581,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
role: null,
|
||||
managerId: null,
|
||||
title: "Endorsement",
|
||||
policyNumber: selectedPolicyNumber,
|
||||
// policyNumber: selectedPolicyNumber,
|
||||
onSubmit: (value) {
|
||||
debugPrint("New Endorsement: $value");
|
||||
enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
||||
@ -608,7 +608,7 @@ class PolicyTabState extends ConsumerState<PolicyTab> {
|
||||
title: "Claims",
|
||||
role: null,
|
||||
managerId: null,
|
||||
policyNumber: selectedPolicyNumber,
|
||||
// policyNumber: selectedPolicyNumber,
|
||||
onSubmit: (value) {
|
||||
debugPrint("New Claim: $value");
|
||||
claimsKey.currentState?.getClaimsList(selectedPolicyNumber);
|
||||
|
||||
@ -51,23 +51,23 @@ class claimListState extends ConsumerState<claimList> {
|
||||
|
||||
// roleId = ref.read(userRoleProvider);
|
||||
// roleId = ref.read(userRoleProvider);
|
||||
|
||||
roleId = ref.read(userRoleProvider);
|
||||
userId = ref.read(userIdProvider);
|
||||
print("G47 => r : $roleId | mId: $id | uId: $userId ");
|
||||
if (userId != null) {
|
||||
getStaffList(id!, userId);
|
||||
getStaffList(managerId, userId, roleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getStaffList(int managerId, role) async {
|
||||
Future<void> getStaffList(int managerId, int userId, role) async {
|
||||
print('G54 => Fns called => $managerId | $role');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final response = await apiService.fetchClaimList(managerId, role);
|
||||
final response = await apiService.fetchClaimList(managerId, userId, role);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final data = response['data'];
|
||||
@ -175,6 +175,10 @@ class claimListState extends ConsumerState<claimList> {
|
||||
];
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
getStaffList(managerId, userId, roleId);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MainLayout(
|
||||
@ -303,10 +307,12 @@ class claimListState extends ConsumerState<claimList> {
|
||||
userId: userId,
|
||||
role: roleId,
|
||||
title: "Claims",
|
||||
policyNumber: 'POC_n1',
|
||||
// policyNumber: 'POC_n1',
|
||||
// policyNumber: selectedPolicyNumber,
|
||||
onSubmit: (value) {
|
||||
debugPrint("New Claims: $value");
|
||||
|
||||
refresh();
|
||||
// enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
||||
|
||||
// Update claim list or call API
|
||||
|
||||
@ -49,19 +49,23 @@ class endosementState extends ConsumerState<endosement> {
|
||||
userId = ref.read(userIdProvider);
|
||||
print("F46 => r : $roleId | mId: $id | uId: $userId ");
|
||||
if (userId != null) {
|
||||
getStaffList(userId, roleId);
|
||||
getStaffList(managerId, userId, roleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getStaffList(int managerId, role) async {
|
||||
Future<void> getStaffList(int managerId, userId, role) async {
|
||||
print('F53 => Fns called => $managerId | $role');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
final response = await apiService.fetchEndorsementList(managerId, role);
|
||||
final response = await apiService.fetchEndorsementList(
|
||||
managerId,
|
||||
userId,
|
||||
role,
|
||||
);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final data = response['data'];
|
||||
@ -111,6 +115,10 @@ class endosementState extends ConsumerState<endosement> {
|
||||
return sortedData.sublist(startIndex, endIndex);
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
getStaffList(managerId, userId, roleId);
|
||||
}
|
||||
|
||||
void filterData(String query) {
|
||||
print("FilterDAta - $query");
|
||||
setState(() {
|
||||
@ -171,7 +179,7 @@ class endosementState extends ConsumerState<endosement> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MainLayout(
|
||||
title: "Endosement",
|
||||
title: "Endorsement",
|
||||
body: Container(
|
||||
// color: Colors.yellow.shade50,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
@ -293,12 +301,12 @@ class endosementState extends ConsumerState<endosement> {
|
||||
userId: userId,
|
||||
role: roleId,
|
||||
title: "Endorsement",
|
||||
policyNumber: '1',
|
||||
// policyNumber: '1',
|
||||
// policyNumber: selectedPolicyNumber,
|
||||
onSubmit: (value) {
|
||||
debugPrint("New Endorsement: $value");
|
||||
// enrollKey.currentState?.getEndrosmentList(selectedPolicyNumber);
|
||||
|
||||
refresh();
|
||||
// Update claim list or call API
|
||||
},
|
||||
),
|
||||
|
||||
@ -239,62 +239,74 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 26),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.phone_outlined,
|
||||
size: 20,
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
profileData?['mobile'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.email_outlined,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
profileData?['email'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if ((roleId != 1) &&
|
||||
(roleId != 2) &&
|
||||
(roleId != 3)) ...[
|
||||
if (profileData?['mobile'] != null ||
|
||||
profileData?['mobile'] != '') ...[
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.location_on_outlined,
|
||||
Icons.phone_outlined,
|
||||
size: 20,
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
profileData?['mobile'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
if (profileData?['email'] != null ||
|
||||
profileData?['email'] != '') ...[
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.email_outlined,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
child: Text(
|
||||
profileData?['address'] ?? '-',
|
||||
style: _dataBold,
|
||||
softWrap: true,
|
||||
),
|
||||
Text(
|
||||
profileData?['email'] ?? '-',
|
||||
style: _dataBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
|
||||
if ((roleId != 2) && (roleId != 3)) ...[
|
||||
if (profileData?['address'] != null ||
|
||||
profileData?['address'] != '') ...[
|
||||
if ((roleId != 1) &&
|
||||
(roleId != 2) &&
|
||||
(roleId != 3)) ...[
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.location_on_outlined,
|
||||
size: 18,
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
|
||||
Expanded(
|
||||
child: Text(
|
||||
profileData?['address'] ?? '-',
|
||||
style: _dataBold,
|
||||
softWrap: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
],
|
||||
|
||||
if ((roleId != 1) &&
|
||||
(roleId != 2) &&
|
||||
(roleId != 3)) ...[
|
||||
// Staff, Handler doesn't have this part Only Manager and agent have
|
||||
Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
|
||||
@ -93,8 +93,8 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
||||
final prefroleId = ref.read(userRoleProvider);
|
||||
|
||||
print("B81 => roleId: $prefroleId | userId: $prefuserid ");
|
||||
if (prefuserid != null) {
|
||||
getParnterDashBrdList(prefuserid);
|
||||
if (prefmanagerid != null) {
|
||||
getParnterDashBrdList(prefmanagerid);
|
||||
// getStaffList(prefmanagerid!, prefroleId, prefuserid);
|
||||
}
|
||||
});
|
||||
@ -324,39 +324,46 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Performing Partner ( Top 50 )',
|
||||
style: _chartHeader,
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 8.0,
|
||||
bottom: 16.0,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Performing Partner ( Top 50 )',
|
||||
style: _chartHeader,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Text(
|
||||
isPerfomingAgntPolicy
|
||||
? "Policies"
|
||||
: "Premium",
|
||||
style: _styleSmall1,
|
||||
),
|
||||
|
||||
Transform.scale(
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
value: isPerfomingAgntPolicy,
|
||||
activeColor: Colors.teal,
|
||||
activeTrackColor: Colors.grey.shade200,
|
||||
inactiveThumbColor: Colors.orange,
|
||||
inactiveTrackColor: Colors.white,
|
||||
onChanged: (val) {
|
||||
setState(
|
||||
() => isPerfomingAgntPolicy = val,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
// Text(
|
||||
// isPerfomingAgntPolicy
|
||||
// ? "Policies"
|
||||
// : "Premium",
|
||||
// style: _styleSmall1,
|
||||
// ),
|
||||
//
|
||||
// Transform.scale(
|
||||
// scale: 0.5,
|
||||
// child: Switch(
|
||||
// value: isPerfomingAgntPolicy,
|
||||
// activeColor: Colors.teal,
|
||||
// activeTrackColor: Colors.grey.shade200,
|
||||
// inactiveThumbColor: Colors.orange,
|
||||
// inactiveTrackColor: Colors.white,
|
||||
// onChanged: (val) {
|
||||
// setState(
|
||||
// () => isPerfomingAgntPolicy = val,
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: Performance(
|
||||
title: "Performing Partner",
|
||||
@ -497,7 +504,7 @@ class _PerformanceState extends State<Performance> {
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
"S.NO",
|
||||
"S.no.",
|
||||
textAlign: TextAlign.left,
|
||||
style: _headerStyle,
|
||||
),
|
||||
@ -518,20 +525,24 @@ class _PerformanceState extends State<Performance> {
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
|
||||
(widget.title == 'Performing Partner')
|
||||
? Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
widget.isPerfomingAgntPolicy
|
||||
? "Policy Count"
|
||||
: "Premium Count",
|
||||
|
||||
textAlign: TextAlign.center,
|
||||
style: _headerStyle,
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
if (widget.title == 'Performing Partner') ...[
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
"Policy Count",
|
||||
textAlign: TextAlign.center,
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
"Premium Amount",
|
||||
textAlign: TextAlign.center,
|
||||
style: _headerStyle,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -586,30 +597,47 @@ class _PerformanceState extends State<Performance> {
|
||||
),
|
||||
),
|
||||
|
||||
(widget.title == 'Performing Partner')
|
||||
? Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
isPerfomingAgntPolicy
|
||||
? (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(),
|
||||
if (widget.title == 'Performing Partner') ...[
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
row['policy_count'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
row['total_premium_amount'] ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: _tableDataStyle,
|
||||
),
|
||||
),
|
||||
],
|
||||
// (widget.title == 'Performing Partner')
|
||||
// ? Expanded(
|
||||
// flex: 1,
|
||||
// child: Text(
|
||||
// isPerfomingAgntPolicy
|
||||
// ? (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 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<List<List<dynamic>>> staffChartData = [];
|
||||
List<List<List<dynamic>>> staffChartData = [];
|
||||
|
||||
double maxPremium = 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 {
|
||||
// print('getClaimList called MagId - $managerId - $role');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
// dynamic id = widget.policyNumber;
|
||||
print('getProductivityDshID - $id');
|
||||
|
||||
try {
|
||||
final response = await apiService.findProductivityDashboardData(
|
||||
id,
|
||||
SelctdProductivityproduct,
|
||||
);
|
||||
|
||||
if (response['status'] == 'success') {
|
||||
final data = response['data'];
|
||||
print('getProductivityDshBdData - ${response['data']}');
|
||||
if (response['status'] != 'success') {
|
||||
setState(() {
|
||||
if (data is Map<String, dynamic>) {
|
||||
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');
|
||||
isLoading = false;
|
||||
});
|
||||
|
||||
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 = [];
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
print('Exception occurred: $e');
|
||||
} 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() {
|
||||
double parseDouble(dynamic value) {
|
||||
if (value == null) return 0.0;
|
||||
@ -241,17 +305,6 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
}).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() {
|
||||
double parseDouble(dynamic value) {
|
||||
if (value == null) return 0.0;
|
||||
@ -297,52 +350,53 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
// color: Colors.amber.shade100,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Hide and Show Charts : ', style: _styleSmall1),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Transform.scale(
|
||||
scale: 0.75,
|
||||
child: Checkbox(
|
||||
value: showStaff,
|
||||
onChanged: (val) {
|
||||
setState(() => showStaff = val!);
|
||||
},
|
||||
),
|
||||
),
|
||||
Text(
|
||||
// showStaff ? "Staff" : "Staff Hidden",
|
||||
"Staff",
|
||||
style: _styleSmall2,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// SizedBox(width: 10),
|
||||
//
|
||||
// Row(
|
||||
// children: [
|
||||
// Transform.scale(
|
||||
// scale: 0.75,
|
||||
// child: Checkbox(
|
||||
// value: showProduct,
|
||||
// onChanged: (val) {
|
||||
// setState(() => showProduct = val!);
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// // showBroker ? "Broker" : "Broker Hidden",
|
||||
// "Product",
|
||||
// style: _styleSmall2,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text('Hide and Show Charts : ', style: _styleSmall1),
|
||||
//
|
||||
// Row(
|
||||
// children: [
|
||||
// Transform.scale(
|
||||
// scale: 0.75,
|
||||
// child: Checkbox(
|
||||
// value: showStaff,
|
||||
// onChanged: (val) {
|
||||
// setState(() => showStaff = val!);
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// // showStaff ? "Staff" : "Staff Hidden",
|
||||
// "Staff",
|
||||
// style: _styleSmall2,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
//
|
||||
// // SizedBox(width: 10),
|
||||
// //
|
||||
// // Row(
|
||||
// // children: [
|
||||
// // Transform.scale(
|
||||
// // scale: 0.75,
|
||||
// // child: Checkbox(
|
||||
// // value: showProduct,
|
||||
// // onChanged: (val) {
|
||||
// // setState(() => showProduct = val!);
|
||||
// // },
|
||||
// // ),
|
||||
// // ),
|
||||
// // Text(
|
||||
// // // showBroker ? "Broker" : "Broker Hidden",
|
||||
// // "Product",
|
||||
// // style: _styleSmall2,
|
||||
// // ),
|
||||
// // ],
|
||||
// // ),
|
||||
// ],
|
||||
// ),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Expanded(
|
||||
child: Row(
|
||||
@ -361,8 +415,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
Widget insurerContainer() {
|
||||
final chartStaffData = buildStaffBarData();
|
||||
final chartStaffLabels = buildStaffLabels();
|
||||
print('chartStaffData - $chartStaffData');
|
||||
print('chartStaffLabels - $chartStaffLabels');
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(right: 20),
|
||||
@ -378,7 +431,7 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Staff Wise (Previous / Current Month)',
|
||||
'Sales Executive Product Wise (Previous / Current Month)',
|
||||
style: _chartHeader,
|
||||
),
|
||||
),
|
||||
@ -390,99 +443,119 @@ class _ProductivityDashboardState extends ConsumerState<ProductivityDashboard> {
|
||||
scale: 0.5,
|
||||
child: Switch(
|
||||
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),
|
||||
|
||||
// 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(
|
||||
child: CustomStackedBarChart(
|
||||
labels: staffLabels,
|
||||
data: staffChartData,
|
||||
maxY: (maxPremium * 1.1).ceilToDouble(), // a bit of headroom
|
||||
// maxY: (maxPremium * 1.1).ceilToDouble(),
|
||||
maxY: _getSmartMaxValue(),
|
||||
initialRotation: 1,
|
||||
dataList: [],
|
||||
productsList: staffChartData,
|
||||
vehicleTypeNames:
|
||||
staffVehicleTypeNames, // 👈 NEW: Pass vehicle names
|
||||
),
|
||||
),
|
||||
|
||||
legendWidget(),
|
||||
Row(children: [Expanded(child: legendWidget())]),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget productContainer() {
|
||||
final chartProductData = buildProductBarData();
|
||||
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(
|
||||
'Staff 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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: CustomBarChart(
|
||||
dataList: chartProductData,
|
||||
labels: chartProductLabels,
|
||||
),
|
||||
),
|
||||
legendWidget(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
// Widget productContainer() {
|
||||
// final chartProductData = buildProductBarData();
|
||||
// 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(
|
||||
// 'Sales Executive 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),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// SizedBox(height: 10),
|
||||
// Expanded(
|
||||
// child: CustomBarChart(
|
||||
// dataList: chartProductData,
|
||||
// labels: chartProductLabels,
|
||||
// ),
|
||||
// ),
|
||||
// legendWidget(),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget legendWidget() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 5,
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.circle, size: 10, color: Colors.cyan.shade300),
|
||||
SizedBox(width: 2),
|
||||
Text('Current Month', style: _styleSmall1),
|
||||
SizedBox(width: 5),
|
||||
Icon(Icons.circle, size: 10, color: Colors.orange.shade300),
|
||||
SizedBox(width: 2),
|
||||
Text('Previous Month', style: _styleSmall1),
|
||||
// Vehicle type legends (dynamically generated)
|
||||
...vehicleColors.entries.map((entry) {
|
||||
return _legendItem(entry.key, entry.value);
|
||||
}),
|
||||
|
||||
// Separator
|
||||
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),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@ -369,6 +369,7 @@ class EnquiryHandlerState extends ConsumerState<EnquiryListHandler> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
roleId,
|
||||
);
|
||||
|
||||
@ -639,7 +639,9 @@ class CreateProposal_QuickFormState
|
||||
print("Response: ${response.body}");
|
||||
// ToastHelper.showErrorToast(context, 'Proposal Created');
|
||||
reset();
|
||||
|
||||
getQuickQuotationList(managerId);
|
||||
|
||||
// Navigator.of(context).pop();
|
||||
} else if (response.statusCode == 403) {
|
||||
await apiService.clearLocalStorageAndRedirect();
|
||||
@ -699,8 +701,17 @@ class CreateProposal_QuickFormState
|
||||
print("tre1");
|
||||
selectedId = null; // just update field
|
||||
Navigator.of(context).pop();
|
||||
// final prefs = await SharedPreferences.getInstance();
|
||||
// await prefs.setString('QuoteKeyProvider', 'fromQuickQuote');
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// Now safe to do navigation + provider updates
|
||||
final container = ProviderScope.containerOf(context);
|
||||
container.read(enquiryRefreshProvider.notifier).state = true;
|
||||
|
||||
context.go('/enquiryForStaff');
|
||||
});
|
||||
|
||||
context.go('/enquiryForStaff');
|
||||
print("tre11");
|
||||
getQuickQuotationList(managerId);
|
||||
} else if (response.statusCode == 403) {
|
||||
@ -1559,7 +1570,8 @@ class CreateProposal_QuickFormState
|
||||
bordedRad: 5,
|
||||
// backgroundColor: Color(0xFFEDF6F5),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||
// FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||||
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}$')),
|
||||
],
|
||||
// validator: (value) =>
|
||||
// Validators.doubleNumber(value, "PremiumAmount"),
|
||||
|
||||
@ -369,6 +369,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInlineTST> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
roleId,
|
||||
);
|
||||
|
||||
@ -484,6 +484,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
roleId,
|
||||
);
|
||||
|
||||
@ -59,6 +59,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
dynamic idPrimary;
|
||||
dynamic managerId;
|
||||
dynamic dashboardKey;
|
||||
dynamic quickQuotationKey;
|
||||
dynamic SelectedStatus;
|
||||
dynamic SelectedStaffId;
|
||||
String? selectedFileNames;
|
||||
@ -79,6 +80,14 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
List<Map<String, dynamic>> originalData = [];
|
||||
List<Map<String, dynamic>> filteredData = [];
|
||||
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;
|
||||
bool _showFilterRow = false;
|
||||
|
||||
@ -100,6 +109,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
Map<int, bool> isEditingRow = {};
|
||||
Map<int, Map<String, TextEditingController>> rowControllers = {};
|
||||
late ProviderSubscription<bool> refreshSub;
|
||||
|
||||
//---------------------- Enquiry TAB Initializations Starts -------------------------------- //
|
||||
|
||||
@ -139,6 +149,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
String? selectedId;
|
||||
|
||||
// int selectedIndex = 1;
|
||||
int selectedIndex = 0;
|
||||
int autoRefreshIndex = 0;
|
||||
|
||||
@ -213,6 +224,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Timer? timer;
|
||||
int selectedSeconds = 30;
|
||||
bool isActionable = false;
|
||||
bool _listened = false;
|
||||
|
||||
//---------------------- Assign Staff Ends -------------------------------- //
|
||||
//---------------------- Enquiry TAB Initializations Ends -------------------------------- //
|
||||
@ -238,11 +250,13 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
dashboardKey = prefs.getString('dashboardKeyProvider');
|
||||
quickQuotationKey = prefs.getString('QuoteKeyProvider');
|
||||
final dashboardStatus = prefs.getString('dashboardStatusProvider');
|
||||
final dashboardStaffId = prefs.getString('dashboardStaffIdProvider');
|
||||
|
||||
print('handlerIdENQ - $handlerId');
|
||||
print("C72 => r : $roleId | uId: $userId !mID : $managerId ");
|
||||
print('quickQuotationKey');
|
||||
|
||||
print('dashboardKey - $dashboardKey');
|
||||
print('dashboardStatus - $dashboardStatus');
|
||||
@ -277,6 +291,15 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('hansles');
|
||||
getStaffDetailsForEnquiryAssignment(userID);
|
||||
}
|
||||
|
||||
ref.listen(enquiryRefreshProvider, (prev, next) {
|
||||
print('quickQuotationKey1');
|
||||
if (next == true) {
|
||||
print('quickQuotationKey2 - $next');
|
||||
callRefresh();
|
||||
ref.read(enquiryRefreshProvider.notifier).state = false; // reset
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
getVehicleType();
|
||||
@ -284,6 +307,18 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
getInsuranceType();
|
||||
getBroker();
|
||||
getPaymentMode();
|
||||
|
||||
refreshSub = ref.listenManual<bool>(enquiryRefreshProvider, (
|
||||
previous,
|
||||
next,
|
||||
) {
|
||||
if (next == true) {
|
||||
print('refresh triggered Quick Creation');
|
||||
callRefresh();
|
||||
|
||||
ref.read(enquiryRefreshProvider.notifier).state = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> loadPreferences() async {
|
||||
@ -359,6 +394,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
refreshSub.close();
|
||||
_horizontalScrollController.dispose();
|
||||
// ... dispose other controllers ...
|
||||
super.dispose();
|
||||
@ -421,7 +457,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getInsurers() async {
|
||||
print('Insurers called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingInsurers = true;
|
||||
});
|
||||
|
||||
try {
|
||||
@ -444,7 +480,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingInsurers = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -452,7 +488,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getInsuranceType() async {
|
||||
print('getClaimList called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingInsuranceType = true;
|
||||
});
|
||||
|
||||
try {
|
||||
@ -477,7 +513,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingInsuranceType = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -485,7 +521,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getBroker() async {
|
||||
print('getBroker called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingBroker = true;
|
||||
});
|
||||
|
||||
try {
|
||||
@ -508,7 +544,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingBroker = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -516,7 +552,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getPaymentMode() async {
|
||||
print('getPaymentMode called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingPaymentMode = true;
|
||||
});
|
||||
|
||||
try {
|
||||
@ -541,7 +577,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingPaymentMode = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -549,12 +585,13 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getStaffDetailsForEnquiryAssignment(int id) async {
|
||||
print('getStaffDetailsForEnquiryAssignment called By handler');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingStaffEnqAssign = true;
|
||||
});
|
||||
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
roleId,
|
||||
);
|
||||
@ -578,7 +615,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingStaffEnqAssign = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -593,7 +630,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
}) async {
|
||||
print('DAJJshA72 => Fns called => $managerId | $role');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingStaffList = true;
|
||||
});
|
||||
|
||||
dynamic fromDt;
|
||||
@ -612,7 +649,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
|
||||
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);
|
||||
|
||||
print('PrevPending FROM TO - $fromDt - $toDt');
|
||||
@ -635,7 +672,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print("ENQ LIST PAGE");
|
||||
|
||||
final today = DateTime.now();
|
||||
fromDt = dateFormat.format(today.subtract(Duration(days: 5)));
|
||||
fromDt = dateFormat.format(today.subtract(Duration(days: 2)));
|
||||
// fromDt = dateFormat.format(today);
|
||||
toDt = dateFormat.format(today);
|
||||
|
||||
@ -694,13 +731,13 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('ToDate : $toDate');
|
||||
|
||||
setState(() {
|
||||
if (SelectedStatus == 'Completed' || autoRefreshIndex == 1) {
|
||||
selectedIndex = 1;
|
||||
SelectedStatus = 'Completed';
|
||||
} else {
|
||||
selectedIndex = 0;
|
||||
SelectedStatus = 'OtherThenCompleted';
|
||||
}
|
||||
// if (SelectedStatus == 'Completed' || autoRefreshIndex == 1) {
|
||||
// selectedIndex = 1;
|
||||
// SelectedStatus = 'Completed';
|
||||
// } else {
|
||||
// selectedIndex = 0;
|
||||
// SelectedStatus = 'OtherThenCompleted';
|
||||
// }
|
||||
controllers['startDate']?.text = fromDate;
|
||||
controllers['endDate']?.text = toDate;
|
||||
if (data is List) {
|
||||
@ -721,7 +758,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingStaffList = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1516,7 +1553,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getVehicleType() async {
|
||||
print('getClaimList called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingVehicleType = true;
|
||||
});
|
||||
|
||||
try {
|
||||
@ -1541,7 +1578,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingVehicleType = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1549,7 +1586,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Future<void> getAgentList(id) async {
|
||||
print('getAgentListData called');
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
isLoadingAgentList = true;
|
||||
});
|
||||
|
||||
try {
|
||||
@ -1573,7 +1610,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print('Exception occurred: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
isLoadingAgentList = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -3472,7 +3509,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
"created_on",
|
||||
"agent_name",
|
||||
"assigned_to_name",
|
||||
"insurer_name",
|
||||
"insurer_short_name",
|
||||
"reg_no",
|
||||
"insured_name",
|
||||
"updated_on",
|
||||
@ -4003,6 +4040,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
item['insurer_short_name'] != null
|
||||
? item['insurer_short_name']
|
||||
: '-',
|
||||
|
||||
style: _dataBoldthm2,
|
||||
),
|
||||
),
|
||||
@ -4012,6 +4050,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
item['broker_name'] != null
|
||||
? _truncateText(item['broker_name'], 8)
|
||||
: '-',
|
||||
|
||||
style: _dataBoldthm4,
|
||||
),
|
||||
),
|
||||
@ -4093,7 +4132,11 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
border: Border.all(color: Color(0xFFE2E8F0)),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Text(item['reg_no'] ?? '-', style: _dataBoldthm3),
|
||||
child: Text(
|
||||
item['reg_no'] ?? '-',
|
||||
textAlign: TextAlign.center,
|
||||
style: _dataBoldthm3,
|
||||
),
|
||||
),
|
||||
// ),
|
||||
// child: Text(item['reg_no'] ?? '-', style: _dataBold),
|
||||
@ -4267,40 +4310,40 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
Material(
|
||||
color: Colors.white,
|
||||
child: InkWell(
|
||||
onTap: null,
|
||||
// hoverColor: Color(0xFFEAF6F4),
|
||||
// onTap: (item['enquiry_status'] == 'Completed')
|
||||
// ? () async {
|
||||
// final prefs =
|
||||
// await SharedPreferences.getInstance();
|
||||
//
|
||||
// // ✅ Remove old value (if any)
|
||||
// await prefs.remove('enqStaffDataId');
|
||||
//
|
||||
// // ✅ Save the new id
|
||||
// await prefs.setString(
|
||||
// 'enqStaffDataId',
|
||||
// id.toString(),
|
||||
// );
|
||||
//
|
||||
// // Read it back if needed
|
||||
// final dynamic? enqStaffDataId = prefs.getString(
|
||||
// 'enqStaffDataId',
|
||||
// );
|
||||
//
|
||||
// // ✅ Update provider too
|
||||
// ref
|
||||
// .read(quotationStaffIdProvider.notifier)
|
||||
// .state =
|
||||
// enqStaffDataId;
|
||||
//
|
||||
// buildPolicyCreatedStatusActions(
|
||||
// context,
|
||||
// status,
|
||||
// item['id'],
|
||||
// );
|
||||
// }
|
||||
// : null,
|
||||
// onTap: null,
|
||||
hoverColor: Color(0xFFEAF6F4),
|
||||
onTap: (item['enquiry_status'] == 'Completed')
|
||||
? () async {
|
||||
final prefs =
|
||||
await SharedPreferences.getInstance();
|
||||
|
||||
// ✅ Remove old value (if any)
|
||||
await prefs.remove('enqStaffDataId');
|
||||
|
||||
// ✅ Save the new id
|
||||
await prefs.setString(
|
||||
'enqStaffDataId',
|
||||
id.toString(),
|
||||
);
|
||||
|
||||
// Read it back if needed
|
||||
final dynamic? enqStaffDataId = prefs.getString(
|
||||
'enqStaffDataId',
|
||||
);
|
||||
|
||||
// ✅ Update provider too
|
||||
ref
|
||||
.read(quotationStaffIdProvider.notifier)
|
||||
.state =
|
||||
enqStaffDataId;
|
||||
|
||||
buildPolicyCreatedStatusActions(
|
||||
context,
|
||||
status,
|
||||
item['id'],
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 2.0),
|
||||
margin: EdgeInsets.symmetric(vertical: 2),
|
||||
@ -4963,6 +5006,10 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
print(
|
||||
"❌ Cancel clicked. Ignoring old file.",
|
||||
);
|
||||
ToastHelper.showErrorToast(
|
||||
context,
|
||||
'Please upload a new file. No previous file exists.',
|
||||
);
|
||||
setState(() {
|
||||
print('Clear Fields');
|
||||
selectedFileNames =
|
||||
@ -5257,15 +5304,15 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
setState(() {
|
||||
selectedIndex = index;
|
||||
|
||||
if (selectedIndex == '1') {
|
||||
getStaffList(
|
||||
managerId,
|
||||
roleId,
|
||||
SelectedStatus: 'Completed',
|
||||
);
|
||||
} else {
|
||||
getStaffList(managerId, roleId);
|
||||
}
|
||||
// if (selectedIndex == '1') {
|
||||
// getStaffList(
|
||||
// managerId,
|
||||
// roleId,
|
||||
// SelectedStatus: 'Completed',
|
||||
// );
|
||||
// } else {
|
||||
// getStaffList(managerId, roleId);
|
||||
// }
|
||||
});
|
||||
},
|
||||
child: AnimatedContainer(
|
||||
|
||||
@ -367,6 +367,7 @@ class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
roleId,
|
||||
);
|
||||
|
||||
@ -351,6 +351,7 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
roleId,
|
||||
);
|
||||
@ -413,9 +414,8 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
buildAgentName(context, fromHeader: true),
|
||||
if (roleId != 'staff') ...[buildSelectStaffMem(context)],
|
||||
|
||||
buildAgentName(context, fromHeader: true),
|
||||
buildBroker(context),
|
||||
buildInsurer(context, fromHeader: true),
|
||||
|
||||
|
||||
@ -76,6 +76,8 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
|
||||
String? selectedRegNum;
|
||||
String? selectedStaffName;
|
||||
|
||||
dynamic managerId;
|
||||
|
||||
Map<String, dynamic> dataDetails() {
|
||||
final data = {
|
||||
"id": widget.enquiryPrimaryId,
|
||||
@ -104,7 +106,7 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
|
||||
getInsurers();
|
||||
getBroker();
|
||||
Future.microtask(() {
|
||||
final managerId = ref.watch(managerIdProvider);
|
||||
managerId = ref.watch(managerIdProvider);
|
||||
// final handlerId = ref.watch(handlerIdProvider);
|
||||
role = ref.watch(userRoleProvider);
|
||||
final userID = ref.watch(userIdProvider);
|
||||
@ -193,6 +195,7 @@ class _AddDialogState extends ConsumerState<AssignStaffDialog> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
role,
|
||||
);
|
||||
|
||||
@ -1,20 +1,38 @@
|
||||
// custom_stacked_bar_chart.dart
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.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 {
|
||||
final List<String> labels;
|
||||
final List<List<List<dynamic>>>
|
||||
data; // data[group][stackIndex] = [start, end, color]
|
||||
final List<dynamic> dataList;
|
||||
final double maxY;
|
||||
final int initialRotation;
|
||||
final List<List<List<dynamic>>> productsList;
|
||||
final List<List<String>>? vehicleTypeNames;
|
||||
final Map<String, Color>? vehicleColorMap; // Dynamic color mapping
|
||||
|
||||
const CustomStackedBarChart({
|
||||
super.key,
|
||||
required this.labels,
|
||||
required this.data,
|
||||
required this.dataList,
|
||||
this.maxY = 100.0,
|
||||
this.initialRotation = 1,
|
||||
required this.productsList,
|
||||
this.vehicleTypeNames,
|
||||
this.vehicleColorMap,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -30,89 +48,50 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
final maxY = widget.maxY;
|
||||
final maxY = widget.maxY <= 0 ? 100.0 : widget.maxY;
|
||||
|
||||
return AspectRatio(
|
||||
aspectRatio: 1.6,
|
||||
child: BarChart(
|
||||
BarChartData(
|
||||
alignment: BarChartAlignment.center,
|
||||
alignment: BarChartAlignment.spaceAround,
|
||||
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(
|
||||
show: true,
|
||||
checkToShowHorizontalLine: (value) => value % (maxY / 5) == 0,
|
||||
getDrawingHorizontalLine: (value) =>
|
||||
FlLine(color: Colors.grey.withOpacity(0.12), strokeWidth: 0.8),
|
||||
// drawVerticalLine: true,
|
||||
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),
|
||||
barTouchData: BarTouchData(
|
||||
enabled: true,
|
||||
touchTooltipData: BarTouchTooltipData(
|
||||
tooltipRoundedRadius: 6,
|
||||
tooltipPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 6,
|
||||
// borderData: FlBorderData(show: false),
|
||||
borderData: FlBorderData(
|
||||
show: true,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: AppColors.contentColorBlack,
|
||||
width: 0.1,
|
||||
),
|
||||
fitInsideHorizontally: true,
|
||||
fitInsideVertically: true,
|
||||
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||
return BarTooltipItem(
|
||||
'${rod.toY.toStringAsFixed(2)}',
|
||||
GoogleFonts.poppins(
|
||||
color: Colors.black,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
);
|
||||
},
|
||||
right: BorderSide(color: AppColors.contentColorBlack, width: 0.1),
|
||||
),
|
||||
),
|
||||
titlesData: FlTitlesData(
|
||||
@ -122,8 +101,9 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
||||
reservedSize: 56,
|
||||
getTitlesWidget: (value, meta) {
|
||||
final i = value.toInt();
|
||||
if (i < 0 || i >= widget.labels.length)
|
||||
if (i < 0 || i >= widget.labels.length) {
|
||||
return const SizedBox();
|
||||
}
|
||||
return SideTitleWidget(
|
||||
meta: meta,
|
||||
child: Text(
|
||||
@ -141,11 +121,18 @@ class _CustomStackedBarChartState extends State<CustomStackedBarChart> {
|
||||
rightTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: 40,
|
||||
reservedSize: 50,
|
||||
getTitlesWidget: (value, meta) {
|
||||
return Text(
|
||||
value.toInt().toString(),
|
||||
style: GoogleFonts.inter(fontSize: 9),
|
||||
return Transform.rotate(
|
||||
angle: -3,
|
||||
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(),
|
||||
topTitles: const AxisTitles(),
|
||||
),
|
||||
barGroups: List.generate(
|
||||
widget.data.length,
|
||||
(i) => _generateGroup(i),
|
||||
barTouchData: BarTouchData(
|
||||
enabled: true,
|
||||
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,
|
||||
),
|
||||
),
|
||||
|
||||
@ -80,6 +80,7 @@ class _DateFilterRowState extends ConsumerState<DateFilterRow> {
|
||||
String? selectedStaff;
|
||||
String? selectedStaffName;
|
||||
dynamic role;
|
||||
dynamic managerId;
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
@ -89,7 +90,7 @@ class _DateFilterRowState extends ConsumerState<DateFilterRow> {
|
||||
apiService = ApiService();
|
||||
|
||||
Future.microtask(() {
|
||||
final managerId = ref.watch(managerIdProvider);
|
||||
managerId = ref.watch(managerIdProvider);
|
||||
final userID = ref.watch(userIdProvider);
|
||||
// final handlerId = ref.watch(handlerIdProvider);
|
||||
role = ref.watch(userRoleProvider);
|
||||
@ -118,6 +119,7 @@ class _DateFilterRowState extends ConsumerState<DateFilterRow> {
|
||||
try {
|
||||
// final response = await apiService.fetchStaffUserList(id, role);
|
||||
final response = await apiService.fetchStaffListForEnquiryAssignDropDown(
|
||||
managerId,
|
||||
id,
|
||||
role,
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user