dashbaord login page changes
This commit is contained in:
parent
a52b8d6c04
commit
9cbb1d8cd5
File diff suppressed because one or more lines are too long
@ -133,7 +133,6 @@ class ApiService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<Map<String, dynamic>> logoutUsingAPI(agentId) async {
|
Future<Map<String, dynamic>> logoutUsingAPI(agentId) async {
|
||||||
// print(_token);
|
// print(_token);
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
@ -177,8 +176,8 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. UNAUTHORIZED / FORBIDDEN (The 401/403 Fix)
|
// 3. UNAUTHORIZED / FORBIDDEN (The 401/403 Fix)
|
||||||
if ((response.statusCode == 401 && body['status'] == 401) || (response.statusCode == 403 && body['status'] == 403)) {
|
if ((response.statusCode == 401 && body['status'] == 401) ||
|
||||||
|
(response.statusCode == 403 && body['status'] == 403)) {
|
||||||
// Perform cleanup
|
// Perform cleanup
|
||||||
await AuthService.clearToken();
|
await AuthService.clearToken();
|
||||||
|
|
||||||
@ -196,10 +195,8 @@ class ApiService {
|
|||||||
|
|
||||||
// 4. ALL OTHER ERRORS
|
// 4. ALL OTHER ERRORS
|
||||||
throw Exception('Server Error: ${response.statusCode}');
|
throw Exception('Server Error: ${response.statusCode}');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<Map<String, dynamic>> CheckDuplicate(
|
Future<Map<String, dynamic>> CheckDuplicate(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
String value,
|
String value,
|
||||||
@ -454,6 +451,8 @@ class ApiService {
|
|||||||
} else if (path == 'PerformingTop50') {
|
} else if (path == 'PerformingTop50') {
|
||||||
pathVal =
|
pathVal =
|
||||||
'dashboard/downloadAgentMonthlyPoliciesExcel?manager_id=$managerId&agent_id=$id';
|
'dashboard/downloadAgentMonthlyPoliciesExcel?manager_id=$managerId&agent_id=$id';
|
||||||
|
} else if (path == 'PerformingAgentAll50') {
|
||||||
|
pathVal = 'dashboard/downloadT50AgentPoliciesExcel?manager_id=$managerId';
|
||||||
} else if (path == 'NonPerformingBelow50K') {
|
} else if (path == 'NonPerformingBelow50K') {
|
||||||
pathVal = 'dashboard/downloadLowPremiumAgentExcel?manager_id=$managerId';
|
pathVal = 'dashboard/downloadLowPremiumAgentExcel?manager_id=$managerId';
|
||||||
} else {
|
} else {
|
||||||
@ -1972,10 +1971,10 @@ class ApiService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> generatePolicyExcel(managerId, fromDate, toDate) async {
|
||||||
Future<void> generatePolicyExcel(managerId,fromDate,toDate) async {
|
final url = Uri.parse(
|
||||||
|
'${Env.apiUrl}reports/policy-excel?manager_id=$managerId&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',
|
||||||
final url = Uri.parse('${Env.apiUrl}reports/policy-excel?manager_id=$managerId&from_date=${fromDate ?? ''}&to_date=${toDate ?? ''}',);
|
);
|
||||||
|
|
||||||
print('getPdfDownload policy-excel - $url');
|
print('getPdfDownload policy-excel - $url');
|
||||||
await _initializeToken();
|
await _initializeToken();
|
||||||
@ -2042,14 +2041,15 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchAuditHistory(id) async {
|
Future<Map<String, dynamic>> fetchAuditHistory(id) async {
|
||||||
|
print("fetchAuditHistory - $id ");
|
||||||
print( "fetchAuditHistory - $id " );
|
|
||||||
|
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
await _initializeToken();
|
await _initializeToken();
|
||||||
}
|
}
|
||||||
// final url = Uri.parse('${Env.apiUrl}audit/history?table_name=partner_policy&pk=80',);
|
// final url = Uri.parse('${Env.apiUrl}audit/history?table_name=partner_policy&pk=80',);
|
||||||
final url = Uri.parse('${Env.apiUrl}audit/history?table_name=partner_policy&pk=${id ?? ''}',);
|
final url = Uri.parse(
|
||||||
|
'${Env.apiUrl}audit/history?table_name=partner_policy&pk=${id ?? ''}',
|
||||||
|
);
|
||||||
|
|
||||||
final headers = {
|
final headers = {
|
||||||
'Authorization': 'Bearer $_token' ?? '',
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:easy_loading_button/easy_loading_button.dart';
|
import 'package:easy_loading_button/easy_loading_button.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
class CommonButton extends StatelessWidget {
|
class CommonButton extends StatelessWidget {
|
||||||
final String text;
|
final String text;
|
||||||
@ -25,10 +26,10 @@ class CommonButton extends StatelessWidget {
|
|||||||
type: EasyButtonType.elevated,
|
type: EasyButtonType.elevated,
|
||||||
idleStateWidget: Text(
|
idleStateWidget: Text(
|
||||||
text,
|
text,
|
||||||
style: TextStyle(
|
style: GoogleFonts.poppins(
|
||||||
color: textColor,
|
color: textColor,
|
||||||
fontSize: 16,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
loadingStateWidget: const CircularProgressIndicator(
|
loadingStateWidget: const CircularProgressIndicator(
|
||||||
|
|||||||
@ -239,11 +239,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 26),
|
const SizedBox(height: 26),
|
||||||
if (profileData?['mobile'] != null ||
|
if (hasValidValue(profileData?['mobile'])) ...[
|
||||||
profileData!['mobile']
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.isNotEmpty) ...[
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
const Icon(
|
||||||
@ -260,11 +256,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
],
|
],
|
||||||
if (profileData?['email'] != null ||
|
if (hasValidValue(profileData?['email'])) ...[
|
||||||
profileData!['email']
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.isNotEmpty) ...[
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
const Icon(
|
||||||
@ -282,11 +274,7 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
|
|
||||||
if (profileData?['address'] != null &&
|
if (hasValidValue(profileData?['address'])) ...[
|
||||||
profileData!['address']
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.isNotEmpty) ...[
|
|
||||||
if ((roleId != 1) &&
|
if ((roleId != 1) &&
|
||||||
(roleId != 2) &&
|
(roleId != 2) &&
|
||||||
(roleId != 3)) ...[
|
(roleId != 3)) ...[
|
||||||
@ -431,6 +419,12 @@ class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasValidValue(dynamic value) {
|
||||||
|
if (value == null) return false;
|
||||||
|
if (value is String) return value.trim().isNotEmpty;
|
||||||
|
return true; // for numbers, bool, etc.
|
||||||
|
}
|
||||||
|
|
||||||
static final _dataBold = TextStyle(
|
static final _dataBold = TextStyle(
|
||||||
fontSize: 11.8,
|
fontSize: 11.8,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import '../../../../core/services/api_service.dart';
|
|||||||
import '../../../../data/models/bar_data.dart';
|
import '../../../../data/models/bar_data.dart';
|
||||||
import '../../../providers/userRoleProvider.dart';
|
import '../../../providers/userRoleProvider.dart';
|
||||||
import '../../../themes/charts/barChart.dart';
|
import '../../../themes/charts/barChart.dart';
|
||||||
|
import '../../../themes/charts/barChart_horizontal.dart';
|
||||||
import '../../../themes/indicators/input_field_decoration.dart';
|
import '../../../themes/indicators/input_field_decoration.dart';
|
||||||
|
|
||||||
class BussinessDashboard extends ConsumerStatefulWidget {
|
class BussinessDashboard extends ConsumerStatefulWidget {
|
||||||
@ -163,7 +164,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BarData> buildInsurerBarData() {
|
List<Map<String, dynamic>> getSortedInsurerWise() {
|
||||||
double parseDouble(dynamic value) {
|
double parseDouble(dynamic value) {
|
||||||
if (value == null) return 0.0;
|
if (value == null) return 0.0;
|
||||||
if (value is num) return value.toDouble();
|
if (value is num) return value.toDouble();
|
||||||
@ -171,12 +172,45 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filteredInsurerWise.map((item) {
|
final List<Map<String, dynamic>> sorted = List<Map<String, dynamic>>.from(
|
||||||
print('policies_current - ${item['total_policies_current_month']}');
|
filteredInsurerWise,
|
||||||
print('policies_PREV - ${item['total_policies_pre_month']}');
|
);
|
||||||
|
|
||||||
print('premium_current - ${item['total_premium_current_month']}');
|
sorted.sort((a, b) {
|
||||||
print('premium_PREV - ${item['total_premium_pre_month']}');
|
final aCurrent = isInsureWisePolicy
|
||||||
|
? parseDouble(a['total_policies_current_month'])
|
||||||
|
: parseDouble(a['total_premium_current_month']);
|
||||||
|
|
||||||
|
final aPrev = isInsureWisePolicy
|
||||||
|
? parseDouble(a['total_policies_pre_month'])
|
||||||
|
: parseDouble(a['total_premium_pre_month']);
|
||||||
|
|
||||||
|
final bCurrent = isInsureWisePolicy
|
||||||
|
? parseDouble(b['total_policies_current_month'])
|
||||||
|
: parseDouble(b['total_premium_current_month']);
|
||||||
|
|
||||||
|
final bPrev = isInsureWisePolicy
|
||||||
|
? parseDouble(b['total_policies_pre_month'])
|
||||||
|
: parseDouble(b['total_premium_pre_month']);
|
||||||
|
|
||||||
|
final aMax = aCurrent > aPrev ? aCurrent : aPrev;
|
||||||
|
final bMax = bCurrent > bPrev ? bCurrent : bPrev;
|
||||||
|
|
||||||
|
return bMax.compareTo(aMax); // DESC
|
||||||
|
});
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BarData> buildInsurerBarData(List<Map<String, dynamic>> sortedList) {
|
||||||
|
double parseDouble(dynamic value) {
|
||||||
|
if (value == null) return 0.0;
|
||||||
|
if (value is num) return value.toDouble();
|
||||||
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedList.map((item) {
|
||||||
return BarData(
|
return BarData(
|
||||||
Colors.blue,
|
Colors.blue,
|
||||||
isInsureWisePolicy
|
isInsureWisePolicy
|
||||||
@ -185,25 +219,23 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
isInsureWisePolicy
|
isInsureWisePolicy
|
||||||
? parseDouble(item['total_policies_pre_month'])
|
? parseDouble(item['total_policies_pre_month'])
|
||||||
: parseDouble(item['total_premium_pre_month']),
|
: parseDouble(item['total_premium_pre_month']),
|
||||||
item['insurer_id'] != null ? item['insurer_id'] : '0',
|
item['insurer_id'] ?? '0',
|
||||||
'Insurer',
|
'Insurer',
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> buildInsurerLabels() {
|
List<String> buildInsurerLabels(List<Map<String, dynamic>> sortedList) {
|
||||||
return filteredInsurerWise.map<String>((item) {
|
return sortedList.map<String>((item) {
|
||||||
final name = item['short_name'];
|
final name = item['short_name'];
|
||||||
if (name != null && name.toString().trim().isNotEmpty) {
|
return (name != null && name.toString().trim().isNotEmpty)
|
||||||
return name.toString();
|
? name.toString()
|
||||||
} else {
|
: '';
|
||||||
return item['short_name']?.toString() ?? '';
|
|
||||||
}
|
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BarData> buildBrokerBarData() {
|
List<Map<String, dynamic>> getSortedBrokerWise() {
|
||||||
double parseDouble(dynamic value) {
|
double parseDouble(dynamic value) {
|
||||||
if (value == null) return 0.0;
|
if (value == null) return 0.0;
|
||||||
if (value is num) return value.toDouble();
|
if (value is num) return value.toDouble();
|
||||||
@ -211,12 +243,45 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filteredBrokerWise.map((item) {
|
final List<Map<String, dynamic>> sorted = List<Map<String, dynamic>>.from(
|
||||||
print('policies_current - ${item['total_policies_current_month']}');
|
filteredBrokerWise,
|
||||||
print('policies_PREV - ${item['total_policies_pre_month']}');
|
);
|
||||||
|
|
||||||
print('premium_current - ${item['total_premium_current_month']}');
|
sorted.sort((a, b) {
|
||||||
print('premium_PREV - ${item['total_premium_pre_month']}');
|
final aCurrent = isBrokerWisePolicy
|
||||||
|
? parseDouble(a['total_policies_current_month'])
|
||||||
|
: parseDouble(a['total_premium_current_month']);
|
||||||
|
|
||||||
|
final aPrev = isBrokerWisePolicy
|
||||||
|
? parseDouble(a['total_policies_pre_month'])
|
||||||
|
: parseDouble(a['total_premium_pre_month']);
|
||||||
|
|
||||||
|
final bCurrent = isBrokerWisePolicy
|
||||||
|
? parseDouble(b['total_policies_current_month'])
|
||||||
|
: parseDouble(b['total_premium_current_month']);
|
||||||
|
|
||||||
|
final bPrev = isBrokerWisePolicy
|
||||||
|
? parseDouble(b['total_policies_pre_month'])
|
||||||
|
: parseDouble(b['total_premium_pre_month']);
|
||||||
|
|
||||||
|
final aMax = aCurrent > aPrev ? aCurrent : aPrev;
|
||||||
|
final bMax = bCurrent > bPrev ? bCurrent : bPrev;
|
||||||
|
|
||||||
|
return bMax.compareTo(aMax); // 🔥 DESC
|
||||||
|
});
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BarData> buildBrokerBarData(List<Map<String, dynamic>> sortedList) {
|
||||||
|
double parseDouble(dynamic value) {
|
||||||
|
if (value == null) return 0.0;
|
||||||
|
if (value is num) return value.toDouble();
|
||||||
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedList.map((item) {
|
||||||
return BarData(
|
return BarData(
|
||||||
Colors.blue,
|
Colors.blue,
|
||||||
isBrokerWisePolicy
|
isBrokerWisePolicy
|
||||||
@ -225,31 +290,97 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
isBrokerWisePolicy
|
isBrokerWisePolicy
|
||||||
? parseDouble(item['total_policies_pre_month'])
|
? parseDouble(item['total_policies_pre_month'])
|
||||||
: parseDouble(item['total_premium_pre_month']),
|
: parseDouble(item['total_premium_pre_month']),
|
||||||
item['broker_id'] != null ? item['broker_id'] : '0',
|
item['broker_id'] ?? '0',
|
||||||
'Broker',
|
'Broker',
|
||||||
5,
|
5,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> buildBrokerLabels() {
|
List<String> buildBrokerLabels(List<Map<String, dynamic>> sortedList) {
|
||||||
return filteredBrokerWise.map<String>((item) {
|
return sortedList.map<String>((item) {
|
||||||
final name = item['broker_name'];
|
final name = item['broker_name'];
|
||||||
if (name != null && name.toString().trim().isNotEmpty) {
|
return (name != null && name.toString().trim().isNotEmpty)
|
||||||
return name.toString();
|
? name.toString()
|
||||||
} else {
|
: '';
|
||||||
return item['broker_name']?.toString() ?? '';
|
|
||||||
}
|
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> buildBrokerShortNames() {
|
List<String> buildBrokerShortNames(List<Map<String, dynamic>> sortedList) {
|
||||||
return filteredBrokerWise.map<String>((item) {
|
return sortedList.map<String>((item) {
|
||||||
return item['broker_short_name']?.toString() ?? '';
|
return item['broker_short_name']?.toString() ?? '';
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BarData> buildProductBarData() {
|
List<Map<String, dynamic>> getSortedProductWise() {
|
||||||
|
double parseDouble(dynamic value) {
|
||||||
|
if (value == null) return 0.0;
|
||||||
|
if (value is num) return value.toDouble();
|
||||||
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Map<String, dynamic>> sorted = List<Map<String, dynamic>>.from(
|
||||||
|
filteredProductWise,
|
||||||
|
);
|
||||||
|
|
||||||
|
sorted.sort((a, b) {
|
||||||
|
final aCurrent = isProductWisePolicy
|
||||||
|
? parseDouble(a['total_policies_current_month'])
|
||||||
|
: parseDouble(a['total_premium_current_month']);
|
||||||
|
|
||||||
|
final aPrev = isProductWisePolicy
|
||||||
|
? parseDouble(a['total_policies_pre_month'])
|
||||||
|
: parseDouble(a['total_premium_pre_month']);
|
||||||
|
|
||||||
|
final bCurrent = isProductWisePolicy
|
||||||
|
? parseDouble(b['total_policies_current_month'])
|
||||||
|
: parseDouble(b['total_premium_current_month']);
|
||||||
|
|
||||||
|
final bPrev = isProductWisePolicy
|
||||||
|
? parseDouble(b['total_policies_pre_month'])
|
||||||
|
: parseDouble(b['total_premium_pre_month']);
|
||||||
|
|
||||||
|
final aMax = aCurrent > aPrev ? aCurrent : aPrev;
|
||||||
|
final bMax = bCurrent > bPrev ? bCurrent : bPrev;
|
||||||
|
|
||||||
|
return bMax.compareTo(aMax); // DESC
|
||||||
|
});
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BarData> buildProductBarData(List<Map<String, dynamic>> sortedList) {
|
||||||
|
double parseDouble(dynamic value) {
|
||||||
|
if (value == null) return 0.0;
|
||||||
|
if (value is num) return value.toDouble();
|
||||||
|
if (value is String) return double.tryParse(value) ?? 0.0;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedList.map((item) {
|
||||||
|
return BarData(
|
||||||
|
Colors.blue,
|
||||||
|
isProductWisePolicy
|
||||||
|
? parseDouble(item['total_policies_current_month'])
|
||||||
|
: parseDouble(item['total_premium_current_month']),
|
||||||
|
isProductWisePolicy
|
||||||
|
? parseDouble(item['total_policies_pre_month'])
|
||||||
|
: parseDouble(item['total_premium_pre_month']),
|
||||||
|
item['vehicle_type']?.toString() ?? '',
|
||||||
|
'Product',
|
||||||
|
10,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> buildProductLabels(List<Map<String, dynamic>> sortedList) {
|
||||||
|
return sortedList.map<String>((item) {
|
||||||
|
return item['vehicle_type']?.toString() ?? '';
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BarData> buildProductBarData1() {
|
||||||
double parseDouble(dynamic value) {
|
double parseDouble(dynamic value) {
|
||||||
if (value == null) return 0.0;
|
if (value == null) return 0.0;
|
||||||
if (value is num) return value.toDouble();
|
if (value is num) return value.toDouble();
|
||||||
@ -278,7 +409,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> buildProductLabels() {
|
List<String> buildProductLabels1() {
|
||||||
return filteredProductWise.map<String>((item) {
|
return filteredProductWise.map<String>((item) {
|
||||||
final name = item['vehicle_type'];
|
final name = item['vehicle_type'];
|
||||||
if (name != null && name.toString().trim().isNotEmpty) {
|
if (name != null && name.toString().trim().isNotEmpty) {
|
||||||
@ -366,47 +497,96 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
legendWidget(),
|
legendWidget(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(showInsurer || showBroker)
|
|
||||||
? Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
(showInsurer || showBroker)
|
||||||
// if (showInsurer) Expanded(child: insurerContainer()),
|
? Expanded(
|
||||||
// if (showBroker) Expanded(child: brokerContainer()),
|
flex: 2,
|
||||||
showInsurer
|
child: Column(
|
||||||
? Expanded(child: insurerContainer())
|
children: [
|
||||||
: SizedBox(),
|
showInsurer
|
||||||
showBroker
|
? Expanded(child: insurerContainer())
|
||||||
? Expanded(child: brokerContainer())
|
: SizedBox(),
|
||||||
: SizedBox(),
|
showInsurer ? SizedBox(height: 10) : SizedBox(),
|
||||||
// showProduct ? Expanded(child: productContainer()) : SizedBox(),
|
|
||||||
],
|
showBroker
|
||||||
),
|
? Expanded(child: brokerContainer())
|
||||||
)
|
: SizedBox(),
|
||||||
: SizedBox(),
|
],
|
||||||
if (showProduct) ...[
|
),
|
||||||
SizedBox(height: 10),
|
)
|
||||||
Expanded(
|
: SizedBox(),
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
showProduct
|
||||||
children: [
|
? Expanded(flex: 1, child: productContainer())
|
||||||
showProduct
|
: SizedBox(),
|
||||||
? Expanded(child: productContainer())
|
],
|
||||||
: SizedBox(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
] else ...[
|
),
|
||||||
SizedBox.shrink(),
|
|
||||||
],
|
// (showInsurer || showBroker)
|
||||||
|
// ? Expanded(
|
||||||
|
// child: Row(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// // if (showInsurer) Expanded(child: insurerContainer()),
|
||||||
|
// // if (showBroker) Expanded(child: brokerContainer()),
|
||||||
|
// showInsurer
|
||||||
|
// ? Expanded(child: insurerContainer())
|
||||||
|
// : SizedBox(),
|
||||||
|
// showBroker
|
||||||
|
// ? Expanded(child: brokerContainer())
|
||||||
|
// : SizedBox(),
|
||||||
|
// // showProduct ? Expanded(child: productContainer()) : SizedBox(),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// : SizedBox(),
|
||||||
|
|
||||||
|
// if (showBroker) ...[
|
||||||
|
// SizedBox(height: 10),
|
||||||
|
// Expanded(
|
||||||
|
// child: Row(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// showBroker ? Expanded(child: brokerContainer()) : SizedBox(),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ] else ...[
|
||||||
|
// SizedBox.shrink(),
|
||||||
|
// ],
|
||||||
|
// if (showProduct) ...[
|
||||||
|
// SizedBox(height: 10),
|
||||||
|
// Expanded(
|
||||||
|
// child: Row(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// showProduct
|
||||||
|
// ? Expanded(child: productContainer())
|
||||||
|
// : SizedBox(),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ] else ...[
|
||||||
|
// SizedBox.shrink(),
|
||||||
|
// ],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget insurerContainer() {
|
Widget insurerContainer() {
|
||||||
final chartInsurerData = buildInsurerBarData();
|
// final chartInsurerData = buildInsurerBarData();
|
||||||
final chartInsurerLabels = buildInsurerLabels();
|
// final chartInsurerLabels = buildInsurerLabels();
|
||||||
|
|
||||||
|
final sortedInsurer = getSortedInsurerWise();
|
||||||
|
|
||||||
|
final chartInsurerData = buildInsurerBarData(sortedInsurer);
|
||||||
|
final chartInsurerLabels = buildInsurerLabels(sortedInsurer);
|
||||||
|
|
||||||
print('chartInsurerData - $chartInsurerData');
|
print('chartInsurerData - $chartInsurerData');
|
||||||
print('chartInsurerLabels - $chartInsurerLabels');
|
print('chartInsurerLabels - $chartInsurerLabels');
|
||||||
return Card(
|
return Card(
|
||||||
@ -460,9 +640,15 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget brokerContainer() {
|
Widget brokerContainer() {
|
||||||
final chartBrokerData = buildBrokerBarData();
|
// final chartBrokerData = buildBrokerBarData();
|
||||||
final chartBrokerLabels = buildBrokerLabels();
|
// final chartBrokerLabels = buildBrokerLabels();
|
||||||
final chartBrokerShortName = buildBrokerShortNames();
|
// final chartBrokerShortName = buildBrokerShortNames();
|
||||||
|
|
||||||
|
final sortedBroker = getSortedBrokerWise();
|
||||||
|
|
||||||
|
final chartBrokerData = buildBrokerBarData(sortedBroker);
|
||||||
|
final chartBrokerLabels = buildBrokerLabels(sortedBroker);
|
||||||
|
final chartBrokerShortNames = buildBrokerShortNames(sortedBroker);
|
||||||
print('chartBrokerData - $chartBrokerData');
|
print('chartBrokerData - $chartBrokerData');
|
||||||
print('chartBrokerLabels - $chartBrokerLabels');
|
print('chartBrokerLabels - $chartBrokerLabels');
|
||||||
return Card(
|
return Card(
|
||||||
@ -498,7 +684,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: CustomBarChart(
|
child: CustomBarChart(
|
||||||
dataList: chartBrokerData,
|
dataList: chartBrokerData,
|
||||||
labels: chartBrokerShortName,
|
labels: chartBrokerShortNames,
|
||||||
shortName: chartBrokerLabels,
|
shortName: chartBrokerLabels,
|
||||||
|
|
||||||
// labels: chartBrokerLabels,
|
// labels: chartBrokerLabels,
|
||||||
@ -513,8 +699,12 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget productContainer() {
|
Widget productContainer() {
|
||||||
final chartProductData = buildProductBarData();
|
final sortedList = getSortedProductWise();
|
||||||
final chartProductLabels = buildProductLabels();
|
|
||||||
|
final chartProductData = buildProductBarData(sortedList);
|
||||||
|
final chartProductLabels = buildProductLabels(sortedList);
|
||||||
|
// final chartProductData = buildProductBarData();
|
||||||
|
// final chartProductLabels = buildProductLabels();
|
||||||
print('chartProductData - $chartProductData');
|
print('chartProductData - $chartProductData');
|
||||||
print('chartProductLabels - $chartProductLabels');
|
print('chartProductLabels - $chartProductLabels');
|
||||||
return Card(
|
return Card(
|
||||||
@ -547,7 +737,7 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomBarChart(
|
child: CustomBarChartHorizontal(
|
||||||
dataList: chartProductData,
|
dataList: chartProductData,
|
||||||
labels: chartProductLabels,
|
labels: chartProductLabels,
|
||||||
),
|
),
|
||||||
@ -563,11 +753,21 @@ class _BussinessDashboardState extends ConsumerState<BussinessDashboard> {
|
|||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.circle, size: 10, color: Colors.cyan.shade300),
|
Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 10,
|
||||||
|
color: Color(0xFF34a9a8),
|
||||||
|
// color: Colors.cyan.shade300
|
||||||
|
),
|
||||||
SizedBox(width: 2),
|
SizedBox(width: 2),
|
||||||
Text('Current Month', style: _styleSmall1),
|
Text('Current Month', style: _styleSmall1),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
Icon(Icons.circle, size: 10, color: Colors.orange.shade300),
|
Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 10,
|
||||||
|
// color: Colors.orange.shade300
|
||||||
|
color: const Color(0xFFA5E4E1),
|
||||||
|
),
|
||||||
SizedBox(width: 2),
|
SizedBox(width: 2),
|
||||||
Text('Previous Month', style: _styleSmall1),
|
Text('Previous Month', style: _styleSmall1),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -332,9 +332,57 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Row(
|
||||||
'Performing Partner ( Top 50 )',
|
mainAxisAlignment:
|
||||||
style: _chartHeader,
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Performing Partner ( Top 50 )',
|
||||||
|
style: _chartHeader,
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(width: 10),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
final path =
|
||||||
|
"PerformingAgentAll50";
|
||||||
|
final id = '';
|
||||||
|
final month = 'current';
|
||||||
|
|
||||||
|
await apiService
|
||||||
|
.generateChartExcel(
|
||||||
|
path,
|
||||||
|
id,
|
||||||
|
month,
|
||||||
|
managerId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Export Excel',
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(
|
||||||
|
5.0,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(
|
||||||
|
0xFF2E7D6E,
|
||||||
|
),
|
||||||
|
// color: const Color(0xFF425B5B),
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(
|
||||||
|
2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
"assets/miscellaneous/export.png",
|
||||||
|
height: 11,
|
||||||
|
width: 11,
|
||||||
|
// color: Colors.green,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -406,6 +454,8 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
SizedBox(width: 10),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
isNonPerfomingAgntPolicy
|
isNonPerfomingAgntPolicy
|
||||||
? "No Business"
|
? "No Business"
|
||||||
@ -429,6 +479,42 @@ class _DashboardState extends ConsumerState<PartnerDashboard> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
final path = isNonPerfomingAgntPolicy
|
||||||
|
? "NoBusiness"
|
||||||
|
: "NonPerformingBelow50K";
|
||||||
|
final id = '';
|
||||||
|
final month = 'current';
|
||||||
|
|
||||||
|
await apiService.generateChartExcel(
|
||||||
|
path,
|
||||||
|
id,
|
||||||
|
month,
|
||||||
|
managerId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Export Excel',
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFF2E7D6E),
|
||||||
|
// color: const Color(0xFF425B5B),
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Image.asset(
|
||||||
|
"assets/miscellaneous/export.png",
|
||||||
|
height: 11,
|
||||||
|
width: 11,
|
||||||
|
// color: Colors.green,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -624,39 +710,43 @@ class _PerformanceState extends State<Performance> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
final path1 = 'PerformingTop50';
|
|
||||||
final path2 = widget.isPerfomingAgntPolicy
|
|
||||||
? "NoBusiness"
|
|
||||||
: "NonPerformingBelow50K";
|
|
||||||
final path = (widget.title == 'Performing Partner')
|
|
||||||
? path1
|
|
||||||
: path2;
|
|
||||||
|
|
||||||
final id =
|
if (widget.title == 'Performing Partner') ...[
|
||||||
((widget.title == 'Performing Partner') &&
|
InkWell(
|
||||||
(row['agent_id'] != null))
|
onTap: () async {
|
||||||
? row['agent_id']
|
final path1 = 'PerformingTop50';
|
||||||
: '';
|
final path2 = widget.isPerfomingAgntPolicy
|
||||||
final month = 'current';
|
? "NoBusiness"
|
||||||
|
: "NonPerformingBelow50K";
|
||||||
|
final path =
|
||||||
|
(widget.title == 'Performing Partner')
|
||||||
|
? path1
|
||||||
|
: path2;
|
||||||
|
|
||||||
await widget.apiService.generateChartExcel(
|
final id =
|
||||||
path,
|
((widget.title == 'Performing Partner') &&
|
||||||
id,
|
(row['agent_id'] != null))
|
||||||
month,
|
? row['agent_id']
|
||||||
widget.managerId,
|
: '';
|
||||||
);
|
final month = 'current';
|
||||||
},
|
|
||||||
child: Tooltip(
|
await widget.apiService.generateChartExcel(
|
||||||
message: 'Click To Download Excel',
|
path,
|
||||||
child: Icon(
|
id,
|
||||||
Icons.download,
|
month,
|
||||||
size: 14,
|
widget.managerId,
|
||||||
color: Colors.green.shade300,
|
);
|
||||||
|
},
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Click To Download Excel',
|
||||||
|
child: Icon(
|
||||||
|
Icons.download,
|
||||||
|
size: 14,
|
||||||
|
color: Colors.green.shade300,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -64,266 +64,347 @@ class _CustomBarChartState extends ConsumerState<CustomBarChart> {
|
|||||||
x: x,
|
x: x,
|
||||||
groupVertically: false,
|
groupVertically: false,
|
||||||
|
|
||||||
// showingTooltipIndicators: [0],
|
// showingTooltipIndicators: [x],
|
||||||
|
showingTooltipIndicators: const [1, 2],
|
||||||
|
|
||||||
// barsSpace: 30,
|
// barsSpace: 30,
|
||||||
barRods: [
|
barRods: [
|
||||||
BarChartRodData(toY: 0, color: Colors.transparent, width: 10),
|
BarChartRodData(toY: 0, color: Colors.transparent, width: 10),
|
||||||
BarChartRodData(
|
BarChartRodData(
|
||||||
toY: value1,
|
toY: value1,
|
||||||
color: Colors.cyan.shade300,
|
color: const Color(0xFF34a9a8),
|
||||||
|
// color: Color(0xFF0FB9B1),
|
||||||
width: 20,
|
width: 20,
|
||||||
|
|
||||||
borderRadius: BorderRadius.circular(0),
|
borderRadius: BorderRadius.circular(0),
|
||||||
),
|
),
|
||||||
// BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6),
|
// BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6),
|
||||||
BarChartRodData(
|
BarChartRodData(
|
||||||
toY: value2,
|
toY: value2,
|
||||||
color: Colors.orange.shade300,
|
color: const Color(0xFFA5E4E1),
|
||||||
|
// color: const Color(0xFF64748B),
|
||||||
|
// color: Colors.orange.shade300,
|
||||||
|
// color: Color(0xFF2F3640),
|
||||||
width: 20,
|
width: 20,
|
||||||
borderRadius: BorderRadius.circular(0),
|
borderRadius: BorderRadius.circular(0),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
showingTooltipIndicators: touchedGroupIndex == x ? [0] : [],
|
// showingTooltipIndicators: touchedGroupIndex == x ? [0] : [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
String compactNumber(num value) {
|
||||||
|
if (value >= 10000000) {
|
||||||
|
return '${(value / 10000000).toStringAsFixed(1).replaceAll('.0', '')}Cr';
|
||||||
|
} else if (value >= 1000000) {
|
||||||
|
return '${(value / 1000000).toStringAsFixed(1).replaceAll('.0', '')}M';
|
||||||
|
} else if (value >= 1000) {
|
||||||
|
return '${(value / 1000).toStringAsFixed(1).replaceAll('.0', '')}K';
|
||||||
|
} else {
|
||||||
|
return value.toInt().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
// return AspectRatio(
|
// return AspectRatio(
|
||||||
// aspectRatio: 1.4,
|
// aspectRatio: 1.4,
|
||||||
//
|
//
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
double getChartWidth() {
|
||||||
|
const double barWidth = 40; // bar + spacing
|
||||||
|
double minWidth =
|
||||||
|
MediaQuery.of(context).size.width * 0.9; // minimum chart width
|
||||||
|
|
||||||
|
final calculatedWidth = widget.dataList.length * barWidth;
|
||||||
|
return calculatedWidth < minWidth ? minWidth : calculatedWidth;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
return SizedBox(
|
return SingleChildScrollView(
|
||||||
width: constraints.maxWidth,
|
scrollDirection: Axis.horizontal,
|
||||||
height: constraints.maxHeight,
|
child: SizedBox(
|
||||||
child: BarChart(
|
// width: constraints.maxWidth,
|
||||||
BarChartData(
|
// height: constraints.maxHeight,
|
||||||
// alignment: BarChartAlignment.spaceBetween,
|
width: getChartWidth(), // 👈 IMPORTANT
|
||||||
alignment: BarChartAlignment.start,
|
height: constraints.maxHeight,
|
||||||
// verticalAxis: Axis.horizontal,
|
child: BarChart(
|
||||||
// rotationQuarterTurns: rotationTurns,
|
BarChartData(
|
||||||
barTouchData: BarTouchData(
|
// alignment: BarChartAlignment.spaceBetween,
|
||||||
enabled: true,
|
alignment: BarChartAlignment.start,
|
||||||
handleBuiltInTouches: true,
|
// verticalAxis: Axis.horizontal,
|
||||||
touchTooltipData: BarTouchTooltipData(
|
// rotationQuarterTurns: rotationTurns,
|
||||||
tooltipMargin: 6,
|
barTouchData: BarTouchData(
|
||||||
tooltipRoundedRadius: 6,
|
enabled: true,
|
||||||
tooltipPadding: const EdgeInsets.symmetric(
|
handleBuiltInTouches: true,
|
||||||
horizontal: 10,
|
touchTooltipData: BarTouchTooltipData(
|
||||||
vertical: 6,
|
tooltipMargin: 20,
|
||||||
),
|
tooltipRoundedRadius: 6,
|
||||||
// ask fl_chart to fit tooltip inside available space
|
getTooltipColor: (group) {
|
||||||
fitInsideVertically:
|
return Colors.transparent; // 👈 tooltip background color
|
||||||
true, // if your fl_chart version supports it
|
|
||||||
fitInsideHorizontally:
|
|
||||||
true, // if your fl_chart version supports it
|
|
||||||
getTooltipItem:
|
|
||||||
(
|
|
||||||
BarChartGroupData group,
|
|
||||||
int groupIndex,
|
|
||||||
BarChartRodData rod,
|
|
||||||
int rodIndex,
|
|
||||||
) {
|
|
||||||
final textColor = rodIndex == 1
|
|
||||||
? Colors.cyan.shade300
|
|
||||||
: Colors.orange.shade300;
|
|
||||||
final textStyle = TextStyle(
|
|
||||||
color: textColor,
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
);
|
|
||||||
|
|
||||||
final formattedValue = indianFormatter.format(
|
|
||||||
rod.toY.round(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return BarTooltipItem(formattedValue, textStyle);
|
|
||||||
// return BarTooltipItem('${rod.toY.round()}', textStyle);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
touchCallback: (FlTouchEvent e, BarTouchResponse? r) async {
|
|
||||||
// optional: change state to highlight tapped group
|
|
||||||
if (r == null || r.spot == null) {
|
|
||||||
setState(() => touchedGroupIndex = -1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(
|
|
||||||
() => touchedGroupIndex = r.spot!.touchedBarGroupIndex,
|
|
||||||
);
|
|
||||||
|
|
||||||
final spot = r.spot!;
|
|
||||||
final groupIndex = spot.touchedBarGroupIndex;
|
|
||||||
final rodIndex = spot.touchedRodDataIndex;
|
|
||||||
|
|
||||||
final barData = widget.dataList[groupIndex];
|
|
||||||
|
|
||||||
final name = barData.chartName;
|
|
||||||
final val = barData.id;
|
|
||||||
final month = rodIndex == 1 ? 'current' : 'previous';
|
|
||||||
print('name - $name');
|
|
||||||
print('val - $val');
|
|
||||||
print('month - $month');
|
|
||||||
print('managerId - $managerId');
|
|
||||||
if (e is FlTapUpEvent) {
|
|
||||||
debugPrint(
|
|
||||||
'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-'
|
|
||||||
' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}',
|
|
||||||
);
|
|
||||||
if (managerId != null) {
|
|
||||||
print('managerId - $managerId');
|
|
||||||
await apiService.generateChartExcel(
|
|
||||||
name,
|
|
||||||
val,
|
|
||||||
month,
|
|
||||||
managerId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
borderData: FlBorderData(
|
|
||||||
show: true,
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(
|
|
||||||
color: AppColors.contentColorBlack,
|
|
||||||
width: 0.1,
|
|
||||||
),
|
|
||||||
left: BorderSide(
|
|
||||||
color: AppColors.contentColorBlack,
|
|
||||||
width: 0.1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
gridData: FlGridData(
|
|
||||||
show: true,
|
|
||||||
// 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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
titlesData: FlTitlesData(
|
|
||||||
bottomTitles: AxisTitles(
|
|
||||||
axisNameWidget: widget.btnName != null
|
|
||||||
? Text(widget.btnName!)
|
|
||||||
: Text(''),
|
|
||||||
axisNameSize: 10,
|
|
||||||
sideTitles: SideTitles(
|
|
||||||
reservedSize: 30,
|
|
||||||
showTitles: true,
|
|
||||||
getTitlesWidget: (value, meta) {
|
|
||||||
final i = value.toInt();
|
|
||||||
if (i >= widget.labels.length) return const SizedBox();
|
|
||||||
final hasShortName =
|
|
||||||
widget.shortName != null &&
|
|
||||||
widget.shortName!.length > i &&
|
|
||||||
widget.shortName![i].trim().isNotEmpty;
|
|
||||||
|
|
||||||
return SideTitleWidget(
|
|
||||||
meta: meta,
|
|
||||||
child: hasShortName
|
|
||||||
? Tooltip(
|
|
||||||
message: widget.shortName![i],
|
|
||||||
child: Text(
|
|
||||||
widget.labels[i],
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 9.5,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
widget.labels[i],
|
|
||||||
style: GoogleFonts.poppins(
|
|
||||||
fontSize: 9.5,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
tooltipPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 7,
|
||||||
|
vertical: 2,
|
||||||
|
),
|
||||||
|
// rotateAngle: -85,
|
||||||
|
// ask fl_chart to fit tooltip inside available space
|
||||||
|
fitInsideVertically:
|
||||||
|
true, // if your fl_chart version supports it
|
||||||
|
fitInsideHorizontally:
|
||||||
|
true, // if your fl_chart version supports it
|
||||||
|
|
||||||
|
getTooltipItem:
|
||||||
|
(
|
||||||
|
BarChartGroupData group,
|
||||||
|
int groupIndex,
|
||||||
|
BarChartRodData rod,
|
||||||
|
int rodIndex,
|
||||||
|
) {
|
||||||
|
if (rod.toY == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final textColor = rodIndex == 1
|
||||||
|
? Color(0xFF34a9a8)
|
||||||
|
: Color(0xFF020050);
|
||||||
|
|
||||||
|
// final textColor = Colors.black87;
|
||||||
|
// final textColor = Color(0xFF020050);
|
||||||
|
// final textColor =;
|
||||||
|
final textStyle = GoogleFonts.poppins(
|
||||||
|
color: textColor,
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight: rodIndex == 1
|
||||||
|
? FontWeight.w600
|
||||||
|
: FontWeight.w400,
|
||||||
|
);
|
||||||
|
|
||||||
|
// final formattedValue = indianFormatter.format(
|
||||||
|
// rod.toY.round(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
final formattedValue = compactNumber(rod.toY);
|
||||||
|
return BarTooltipItem(formattedValue, textStyle);
|
||||||
|
// return BarTooltipItem('${rod.toY.round()}', textStyle);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
touchCallback: (FlTouchEvent e, BarTouchResponse? r) async {
|
||||||
|
// optional: change state to highlight tapped group
|
||||||
|
if (r == null || r.spot == null) {
|
||||||
|
setState(() => touchedGroupIndex = -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(
|
||||||
|
() => touchedGroupIndex = r.spot!.touchedBarGroupIndex,
|
||||||
|
);
|
||||||
|
|
||||||
|
final spot = r.spot!;
|
||||||
|
final groupIndex = spot.touchedBarGroupIndex;
|
||||||
|
final rodIndex = spot.touchedRodDataIndex;
|
||||||
|
|
||||||
|
final barData = widget.dataList[groupIndex];
|
||||||
|
|
||||||
|
final name = barData.chartName;
|
||||||
|
final val = barData.id;
|
||||||
|
final month = rodIndex == 1 ? 'current' : 'previous';
|
||||||
|
print('name - $name');
|
||||||
|
print('val - $val');
|
||||||
|
print('month - $month');
|
||||||
|
print('managerId - $managerId');
|
||||||
|
if (e is FlTapUpEvent) {
|
||||||
|
debugPrint(
|
||||||
|
'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-'
|
||||||
|
' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}',
|
||||||
|
);
|
||||||
|
if (managerId != null) {
|
||||||
|
print('managerId - $managerId');
|
||||||
|
await apiService.generateChartExcel(
|
||||||
|
name,
|
||||||
|
val,
|
||||||
|
month,
|
||||||
|
managerId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
leftTitles: AxisTitles(
|
borderData: FlBorderData(
|
||||||
sideTitles: SideTitles(
|
show: true,
|
||||||
showTitles: true,
|
border: Border(
|
||||||
// interval: 10,
|
bottom: BorderSide(
|
||||||
getTitlesWidget: (value, meta) {
|
color: AppColors.contentColorBlack,
|
||||||
// print("valuevalue - $value");
|
width: 0.1,
|
||||||
|
),
|
||||||
|
left: BorderSide(
|
||||||
|
color: AppColors.contentColorBlack,
|
||||||
|
width: 0.1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
gridData: FlGridData(
|
||||||
|
show: true,
|
||||||
|
// 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
axisNameWidget: widget.btnName != null
|
||||||
|
? Text(widget.btnName!)
|
||||||
|
: Text(''),
|
||||||
|
axisNameSize: 10,
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
reservedSize: 30,
|
||||||
|
showTitles: true,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
if (value == 0) {
|
||||||
|
return const SizedBox.shrink(); // 👈 hide 0
|
||||||
|
}
|
||||||
|
final i = value.toInt();
|
||||||
|
if (i >= widget.labels.length) return const SizedBox();
|
||||||
|
final hasShortName =
|
||||||
|
widget.shortName != null &&
|
||||||
|
widget.shortName!.length > i &&
|
||||||
|
widget.shortName![i].trim().isNotEmpty;
|
||||||
|
|
||||||
final text = value.toInt().toString();
|
return SideTitleWidget(
|
||||||
|
meta: meta,
|
||||||
|
child: hasShortName
|
||||||
|
? Tooltip(
|
||||||
|
message: widget.shortName![i],
|
||||||
|
child: Transform.rotate(
|
||||||
|
angle: -1,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
right: 3.0,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
truncate(widget.labels[i], max: 5),
|
||||||
|
// widget.labels[i],
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Color(0xFF1E293B),
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Tooltip(
|
||||||
|
message: widget.labels[i],
|
||||||
|
child: Transform.rotate(
|
||||||
|
angle: -1,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
right: 3.0,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
truncate(widget.labels[i], max: 5),
|
||||||
|
// widget.[i],
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Color(0xFF1E293B),
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
final bool isLast = value == meta.max;
|
leftTitles: AxisTitles(
|
||||||
// if (isLast) {
|
sideTitles: SideTitles(
|
||||||
// return const SizedBox.shrink(); // 👈 hide last label
|
showTitles: true,
|
||||||
// }
|
// interval: 10,
|
||||||
// print('value: $value');
|
getTitlesWidget: (value, meta) {
|
||||||
// print('text: $text');
|
// print("valuevalue - $value");
|
||||||
// print('length: ${text.length}');
|
|
||||||
// print('isLast: $isLast');
|
final text = value.toInt().toString();
|
||||||
return Transform.rotate(
|
|
||||||
// angle: -3,
|
final bool isLast = value == meta.max;
|
||||||
angle: 0,
|
// if (isLast) {
|
||||||
child: Padding(
|
// return const SizedBox.shrink(); // 👈 hide last label
|
||||||
padding: const EdgeInsets.only(right: 3.0),
|
// }
|
||||||
child: Text(
|
// print('value: $value');
|
||||||
isLast ? '0' : value.toInt().toString(),
|
// print('text: $text');
|
||||||
textAlign: TextAlign.end,
|
// print('length: ${text.length}');
|
||||||
style: GoogleFonts.inter(
|
// print('isLast: $isLast');
|
||||||
fontSize: 9,
|
return Transform.rotate(
|
||||||
color: isLast ? Colors.white : Colors.black,
|
// angle: -3,
|
||||||
fontWeight: isLast
|
angle: 0,
|
||||||
? FontWeight.w100
|
child: Padding(
|
||||||
: FontWeight.w400,
|
padding: const EdgeInsets.only(right: 3.0),
|
||||||
|
child: Text(
|
||||||
|
// isLast ? '0' : value.toInt().toString(),
|
||||||
|
isLast ? '0' : compactNumber(value),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 9,
|
||||||
|
color: isLast ? Colors.white : Colors.black,
|
||||||
|
fontWeight: isLast
|
||||||
|
? FontWeight.w100
|
||||||
|
: FontWeight.w300,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
reservedSize: 45,
|
||||||
reservedSize: 45,
|
),
|
||||||
),
|
),
|
||||||
|
rightTitles: const AxisTitles(),
|
||||||
|
topTitles: const AxisTitles(),
|
||||||
),
|
),
|
||||||
rightTitles: const AxisTitles(),
|
barGroups: widget.dataList.asMap().entries.map((e) {
|
||||||
topTitles: const AxisTitles(),
|
final index = e.key;
|
||||||
|
final data = e.value;
|
||||||
|
print('generateBarGroupBAR - $data');
|
||||||
|
return generateBarGroup(
|
||||||
|
index,
|
||||||
|
data.color,
|
||||||
|
data.value1,
|
||||||
|
data.value2,
|
||||||
|
data.shadowValue,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
groupsSpace: 12,
|
||||||
|
// maxY: widget.maxY,
|
||||||
|
maxY: (widget.dataList != null && widget.dataList!.isNotEmpty)
|
||||||
|
? widget.dataList!
|
||||||
|
.map(
|
||||||
|
(e) =>
|
||||||
|
e.value1 > e.value2 ? e.value1 : e.value2,
|
||||||
|
)
|
||||||
|
.reduce((a, b) => a > b ? a : b) *
|
||||||
|
1.15
|
||||||
|
: 20,
|
||||||
),
|
),
|
||||||
barGroups: widget.dataList.asMap().entries.map((e) {
|
|
||||||
final index = e.key;
|
|
||||||
final data = e.value;
|
|
||||||
print('generateBarGroupBAR - $data');
|
|
||||||
return generateBarGroup(
|
|
||||||
index,
|
|
||||||
data.color,
|
|
||||||
data.value1,
|
|
||||||
data.value2,
|
|
||||||
data.shadowValue,
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
|
|
||||||
// maxY: widget.maxY,
|
|
||||||
maxY: (widget.dataList != null && widget.dataList!.isNotEmpty)
|
|
||||||
? widget.dataList!
|
|
||||||
.map(
|
|
||||||
(e) => e.value1 > e.value2 ? e.value1 : e.value2,
|
|
||||||
)
|
|
||||||
.reduce((a, b) => a > b ? a : b) +
|
|
||||||
15
|
|
||||||
: 20,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String truncate(String text, {int max = 6}) {
|
||||||
|
if (text.length <= max) return text;
|
||||||
|
return text.substring(0, max);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
401
lib/presentation/themes/charts/barChart_horizontal.dart
Normal file
401
lib/presentation/themes/charts/barChart_horizontal.dart
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import '../../../core/services/api_service.dart';
|
||||||
|
import '../../../data/models/bar_data.dart';
|
||||||
|
import '../../providers/manager_provider.dart';
|
||||||
|
import 'appChartColors.dart';
|
||||||
|
|
||||||
|
class CustomBarChartHorizontal extends ConsumerStatefulWidget {
|
||||||
|
final List<BarData> dataList;
|
||||||
|
final List<String> labels;
|
||||||
|
final List<String>? shortName;
|
||||||
|
final String title;
|
||||||
|
final String? btnName;
|
||||||
|
final double maxY;
|
||||||
|
final int initialRotation;
|
||||||
|
|
||||||
|
const CustomBarChartHorizontal({
|
||||||
|
super.key,
|
||||||
|
required this.dataList,
|
||||||
|
required this.labels,
|
||||||
|
this.shortName,
|
||||||
|
this.btnName,
|
||||||
|
this.title = "Horizontal Bar Chart",
|
||||||
|
this.maxY = 20,
|
||||||
|
this.initialRotation = 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
final shadowColor = const Color(0xFFCCCCCC);
|
||||||
|
|
||||||
|
@override
|
||||||
|
// State<CustomBarChartHorizontal> createState() => _CustomBarChartState();
|
||||||
|
ConsumerState<CustomBarChartHorizontal> createState() =>
|
||||||
|
_CustomBarChartState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomBarChartState extends ConsumerState<CustomBarChartHorizontal> {
|
||||||
|
int touchedGroupIndex = -1;
|
||||||
|
late int rotationTurns;
|
||||||
|
dynamic managerId;
|
||||||
|
late ApiService apiService;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
apiService = ApiService();
|
||||||
|
rotationTurns = widget.initialRotation;
|
||||||
|
Future.microtask(() {
|
||||||
|
managerId = ref.read(managerIdProvider);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final indianFormatter = NumberFormat('#,##,##0', 'en_IN');
|
||||||
|
BarChartGroupData generateBarGroup(
|
||||||
|
int x,
|
||||||
|
Color color,
|
||||||
|
double value1,
|
||||||
|
double value2,
|
||||||
|
double shadowValue,
|
||||||
|
) {
|
||||||
|
return BarChartGroupData(
|
||||||
|
x: x,
|
||||||
|
groupVertically: false,
|
||||||
|
|
||||||
|
// showingTooltipIndicators: [x],
|
||||||
|
showingTooltipIndicators: const [1, 2],
|
||||||
|
|
||||||
|
// barsSpace: 30,
|
||||||
|
barRods: [
|
||||||
|
BarChartRodData(toY: 0, color: Colors.transparent, width: 10),
|
||||||
|
BarChartRodData(
|
||||||
|
toY: value1,
|
||||||
|
color: const Color(0xFF34a9a8),
|
||||||
|
// color: Colors.cyan.shade300,
|
||||||
|
width: 10,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(5),
|
||||||
|
topRight: Radius.circular(5),
|
||||||
|
),
|
||||||
|
// borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
// BarChartRodData(toY: 2, color: Colors.orange.shade300, width: 6),
|
||||||
|
BarChartRodData(
|
||||||
|
toY: value2,
|
||||||
|
color: const Color(0xFFA5E4E1),
|
||||||
|
// color: Colors.orange.shade300,
|
||||||
|
width: 10,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(5),
|
||||||
|
topRight: Radius.circular(5),
|
||||||
|
),
|
||||||
|
// borderRadius: BorderRadius.circular(5),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
// showingTooltipIndicators: touchedGroupIndex == x ? [0] : [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String compactNumber(num value) {
|
||||||
|
if (value >= 10000000) {
|
||||||
|
return '${(value / 10000000).toStringAsFixed(1).replaceAll('.0', '')}Cr';
|
||||||
|
} else if (value >= 1000000) {
|
||||||
|
return '${(value / 1000000).toStringAsFixed(1).replaceAll('.0', '')}M';
|
||||||
|
} else if (value >= 1000) {
|
||||||
|
return '${(value / 1000).toStringAsFixed(1).replaceAll('.0', '')}K';
|
||||||
|
} else {
|
||||||
|
return value.toInt().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// return AspectRatio(
|
||||||
|
// aspectRatio: 1.4,
|
||||||
|
//
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
double getChartWidth() {
|
||||||
|
const double barWidth = 40; // bar + spacing
|
||||||
|
double minWidth =
|
||||||
|
MediaQuery.of(context).size.width * 0.9; // minimum chart width
|
||||||
|
|
||||||
|
final calculatedWidth = widget.dataList.length * barWidth;
|
||||||
|
return calculatedWidth < minWidth ? minWidth : calculatedWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
return SizedBox(
|
||||||
|
// width: constraints.maxWidth,
|
||||||
|
// height: constraints.maxHeight,
|
||||||
|
width: getChartWidth(), // 👈 IMPORTANT
|
||||||
|
height: constraints.maxHeight,
|
||||||
|
child: BarChart(
|
||||||
|
BarChartData(
|
||||||
|
// alignment: BarChartAlignment.spaceBetween,
|
||||||
|
alignment: BarChartAlignment.start,
|
||||||
|
// verticalAxis: Axis.horizontal,
|
||||||
|
rotationQuarterTurns: rotationTurns,
|
||||||
|
barTouchData: BarTouchData(
|
||||||
|
enabled: true,
|
||||||
|
handleBuiltInTouches: true,
|
||||||
|
touchTooltipData: BarTouchTooltipData(
|
||||||
|
tooltipMargin: 6,
|
||||||
|
tooltipRoundedRadius: 6,
|
||||||
|
getTooltipColor: (group) {
|
||||||
|
return Colors.transparent; // 👈 tooltip background color
|
||||||
|
},
|
||||||
|
tooltipPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 7,
|
||||||
|
vertical: 2,
|
||||||
|
),
|
||||||
|
// rotateAngle: -85,
|
||||||
|
// ask fl_chart to fit tooltip inside available space
|
||||||
|
fitInsideVertically:
|
||||||
|
true, // if your fl_chart version supports it
|
||||||
|
fitInsideHorizontally:
|
||||||
|
true, // if your fl_chart version supports it
|
||||||
|
|
||||||
|
getTooltipItem:
|
||||||
|
(
|
||||||
|
BarChartGroupData group,
|
||||||
|
int groupIndex,
|
||||||
|
BarChartRodData rod,
|
||||||
|
int rodIndex,
|
||||||
|
) {
|
||||||
|
if (rod.toY == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// final textColor = rodIndex == 1
|
||||||
|
// ? Colors.cyan.shade500
|
||||||
|
// : Colors.orange.shade500;
|
||||||
|
|
||||||
|
// final textColor = Colors.black;
|
||||||
|
|
||||||
|
final textColor = rodIndex == 1
|
||||||
|
? Color(0xFF34a9a8)
|
||||||
|
: Color(0xFF020050);
|
||||||
|
final textStyle = GoogleFonts.poppins(
|
||||||
|
color: textColor,
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight: rodIndex == 1
|
||||||
|
? FontWeight.w600
|
||||||
|
: FontWeight.w400,
|
||||||
|
);
|
||||||
|
|
||||||
|
// final formattedValue = indianFormatter.format(
|
||||||
|
// rod.toY.round(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
final formattedValue = compactNumber(rod.toY);
|
||||||
|
return BarTooltipItem(formattedValue, textStyle);
|
||||||
|
// return BarTooltipItem('${rod.toY.round()}', textStyle);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
touchCallback: (FlTouchEvent e, BarTouchResponse? r) async {
|
||||||
|
// optional: change state to highlight tapped group
|
||||||
|
if (r == null || r.spot == null) {
|
||||||
|
setState(() => touchedGroupIndex = -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(
|
||||||
|
() => touchedGroupIndex = r.spot!.touchedBarGroupIndex,
|
||||||
|
);
|
||||||
|
|
||||||
|
final spot = r.spot!;
|
||||||
|
final groupIndex = spot.touchedBarGroupIndex;
|
||||||
|
final rodIndex = spot.touchedRodDataIndex;
|
||||||
|
|
||||||
|
final barData = widget.dataList[groupIndex];
|
||||||
|
|
||||||
|
final name = barData.chartName;
|
||||||
|
final val = barData.id;
|
||||||
|
final month = rodIndex == 1 ? 'current' : 'previous';
|
||||||
|
print('name - $name');
|
||||||
|
print('val - $val');
|
||||||
|
print('month - $month');
|
||||||
|
print('managerId - $managerId');
|
||||||
|
if (e is FlTapUpEvent) {
|
||||||
|
debugPrint(
|
||||||
|
'Tapped value → ${rodIndex == 1 ? barData.value1 : barData.value2} -> ${barData.id}-'
|
||||||
|
' ${rodIndex == 1 ? 'current' : 'previous'} -> ${barData.chartName}',
|
||||||
|
);
|
||||||
|
if (managerId != null) {
|
||||||
|
print('managerId - $managerId');
|
||||||
|
await apiService.generateChartExcel(
|
||||||
|
name,
|
||||||
|
val,
|
||||||
|
month,
|
||||||
|
managerId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
borderData: FlBorderData(
|
||||||
|
show: true,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: AppColors.gridLinesColor,
|
||||||
|
// color: AppColors.contentColorBlack,
|
||||||
|
width: 0.1,
|
||||||
|
),
|
||||||
|
right: BorderSide(
|
||||||
|
color: AppColors.gridLinesColor,
|
||||||
|
// color: AppColors.contentColorBlack,
|
||||||
|
width: 0.1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
gridData: FlGridData(
|
||||||
|
show: true,
|
||||||
|
// 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
axisNameWidget: widget.btnName != null
|
||||||
|
? Text(widget.btnName!)
|
||||||
|
: Text(''),
|
||||||
|
axisNameSize: 10,
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
// reservedSize: 90,
|
||||||
|
reservedSize: MediaQuery.of(context).size.width * 0.1,
|
||||||
|
showTitles: true,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
final i = value.toInt();
|
||||||
|
if (i >= widget.labels.length) return const SizedBox();
|
||||||
|
final hasShortName =
|
||||||
|
widget.shortName != null &&
|
||||||
|
widget.shortName!.length > i &&
|
||||||
|
widget.shortName![i].trim().isNotEmpty;
|
||||||
|
|
||||||
|
return SideTitleWidget(
|
||||||
|
meta: meta,
|
||||||
|
child: hasShortName
|
||||||
|
? Tooltip(
|
||||||
|
message: widget.shortName![i],
|
||||||
|
child: Transform.rotate(
|
||||||
|
angle: 0,
|
||||||
|
child: Text(
|
||||||
|
// widget.labels[i],
|
||||||
|
truncate(widget.labels[i], max: 5),
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF1E293B),
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Transform.rotate(
|
||||||
|
angle: 0,
|
||||||
|
child: Text(
|
||||||
|
widget.labels[i],
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 9,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Color(0xFF1E293B),
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
rightTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
// interval: 10,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
// print("valuevalue - $value");
|
||||||
|
|
||||||
|
final text = value.toInt().toString();
|
||||||
|
|
||||||
|
final bool isLast = value == meta.max;
|
||||||
|
// if (isLast) {
|
||||||
|
// return const SizedBox.shrink(); // 👈 hide last label
|
||||||
|
// }
|
||||||
|
// print('value: $value');
|
||||||
|
// print('text: $text');
|
||||||
|
// print('length: ${text.length}');
|
||||||
|
// print('isLast: $isLast');
|
||||||
|
return Transform.rotate(
|
||||||
|
angle: -3,
|
||||||
|
// angle: 0,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 3.0),
|
||||||
|
child: Text(
|
||||||
|
// isLast ? '0' : value.toInt().toString(),
|
||||||
|
isLast ? '0' : compactNumber(value),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 9,
|
||||||
|
// color: isLast ? Colors.white : Colors.black,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: isLast
|
||||||
|
? FontWeight.w100
|
||||||
|
: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
reservedSize: 5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leftTitles: const AxisTitles(),
|
||||||
|
topTitles: const AxisTitles(),
|
||||||
|
),
|
||||||
|
barGroups: widget.dataList.asMap().entries.map((e) {
|
||||||
|
final index = e.key;
|
||||||
|
final data = e.value;
|
||||||
|
print('generateBarGroupBAR - $data');
|
||||||
|
return generateBarGroup(
|
||||||
|
index,
|
||||||
|
data.color,
|
||||||
|
data.value1,
|
||||||
|
data.value2,
|
||||||
|
data.shadowValue,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
groupsSpace: 12,
|
||||||
|
// maxY: widget.maxY,
|
||||||
|
maxY: (widget.dataList != null && widget.dataList!.isNotEmpty)
|
||||||
|
? widget.dataList!
|
||||||
|
.map(
|
||||||
|
(e) => e.value1 > e.value2 ? e.value1 : e.value2,
|
||||||
|
)
|
||||||
|
.reduce((a, b) => a > b ? a : b) *
|
||||||
|
1.15
|
||||||
|
: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String truncate(String text, {int max = 6}) {
|
||||||
|
if (text.length <= max) return text;
|
||||||
|
return text.substring(0, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user