dashbaord login page changes

This commit is contained in:
venbaittech 2025-12-23 09:53:59 +05:30
parent a52b8d6c04
commit 9cbb1d8cd5
9 changed files with 1529 additions and 1021 deletions

File diff suppressed because one or more lines are too long

View File

@ -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' ?? '',

View File

@ -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(

View File

@ -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,

View File

@ -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),
], ],

View File

@ -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

View File

@ -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);
}
} }

View 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);
}
}