chart changes

This commit is contained in:
venbaittech 2025-02-21 09:11:34 +05:30
parent bdcdf737a8
commit a1993712ac
2 changed files with 409 additions and 700 deletions

View File

@ -1346,10 +1346,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
// If chartFilteredData is empty, print the message // If chartFilteredData is empty, print the message
if (chartFilteredData.isEmpty) { if (chartFilteredData.isEmpty) {
if (kDebugMode) { if (kDebugMode) {
print( print("Selected year: ${selectedFilters.firstWhere((f) => f['filter_key'] == 'TIME_PERIOD',
"Selected year: ${selectedFilters.firstWhere((f) => f['filter_key'] == 'TIME_PERIOD', orElse: () => { orElse: () => {'filter_data': ['Unknown']})['filter_data']} - No data for chart: : $chartHeading");
'filter_data': ['Unknown']
})['filter_data']} - No data for chart: : $chartHeading");
} }
// Add the complete chart data to the filteredData list // Add the complete chart data to the filteredData list
@ -1372,6 +1371,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
addedChartIds addedChartIds
.add(chart['chart_heading']); // Track by a unique identifier .add(chart['chart_heading']); // Track by a unique identifier
} }
} }
// List filteredCardData = []; // List filteredCardData = [];
@ -1799,18 +1799,21 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
print("FilteringDAtss START1 - $filterData"); print("FilteringDAtss START1 - $filterData");
print('TABId1 - $tabId'); print('TABId1 - $tabId');
// for (var item in filterData) {
// if (item['filter_key'] == 'TIME_PERIOD') { for (var item in filterData) {
// // Convert the values to integers, sort them, and convert back to strings if (item['filter_key'] == 'TIME_PERIOD') {
// List<int> timePeriodData = item['filter_data'] // Convert the values to integers, sort them, and convert back to strings
// .map<int>((e) => int.parse(e.toString())) // Convert to int List<int> timePeriodData = item['filter_data']
// .toList(); .map<int>((e) => int.parse(e.toString())) // Convert to int
// timePeriodData.sort((a, b) => a.compareTo(b)); // Sort numerically .toList();
// timePeriodData.sort((a, b) => a.compareTo(b)); // Sort numerically
// // Optionally, convert sorted integers back to strings if necessary
// item['filter_data'] = timePeriodData.map((e) => e.toString()).toList(); // Optionally, convert sorted integers back to strings if necessary
// } item['filter_data'] = timePeriodData.map((e) => e.toString()).toList();
// } }
}
print('TABId - $tabId'); print('TABId - $tabId');
print("TABFiltered Data: $filterData"); print("TABFiltered Data: $filterData");
@ -1927,6 +1930,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
}); });
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
int crossAxisCount = cardData.isNotEmpty ? (cardData.length / 2).ceil().clamp(1, 2) : 1;
final color = final color =
Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16)); Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16));
return PopScope( return PopScope(
@ -1938,45 +1945,6 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
child: BaseScaffold( child: BaseScaffold(
key: _scaffoldKey, key: _scaffoldKey,
// backgroundColor: color,
// appBar: AppBar(
// backgroundColor: color,
// elevation: 0,
// actions: [
// // IconButton(
// // onPressed: () {},
// // icon: const Icon(Icons.toggle_off_outlined),
// // ),
// MyToggle(
// // key: toggleKey,
// isOn: locale?.languageCode == 'en',
// knobTextWhenOn: 'ع',
// knobTextWhenOff: 'EN',
// pathColorWhenOn: Colors.grey.shade300,
// pathColorWhenOff: Colors.grey.shade300,
// onTap: () {
// ref.read(localeProvider.notifier).toggleLocale();
// },
// ),
// ],
// leading: IconButton(
// icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
// onPressed: () {
// if (widget.keyParam == 'home') {
// context.go('/myhomepage');
// } else {
// context.go('/uaenumbers');
// }
// },
// ),
// title: Text(
// context.translate(
// 'UAE Numbers',
// 'أرقام الإمارات',
// ),
// style: TextStyle(color: Colors.white),
// ),
// ),
title: Text( title: Text(
context.translate( context.translate(
'UAE Numbers', 'UAE Numbers',
@ -2035,25 +2003,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontFamily: 'Roboto'), fontFamily: 'Roboto'),
), ),
// Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: [
// IconButton(
// onPressed: () {},
// icon: Icon(
// Icons.bookmark_add_outlined,
// color: Colors.white,
// size: 40,
// )),
// IconButton(
// onPressed: () {},
// icon: Icon(
// Icons.share,
// color: Colors.white,
// size: 30,
// )),
// ],
// ),
], ],
), ),
)), )),
@ -2201,6 +2151,15 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
SizedBox( SizedBox(
width: 10), // Horizontal space between items width: 10), // Horizontal space between items
Row( Row(
children: [
GestureDetector(
onTap: () {
showRightSideModal(
context, filterData, chartsData);
},
child: Row(
children: [ children: [
Text( Text(
context.translate( context.translate(
@ -2214,17 +2173,14 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
), ),
SizedBox(width: 10), SizedBox(width: 10),
GestureDetector( Image.asset(
onTap: () {
showRightSideModal(
context, filterData, chartsData);
},
child: Image.asset(
UaeNumbersAssetPath.filterUae, UaeNumbersAssetPath.filterUae,
color: Colors.white, // Set color to white color: Colors.white, // Set color to white
width: 21, width: 21,
height: 21, height: 21,
), ),
],),
) )
// IconButton( // IconButton(
// icon: Icon(Icons.filter_alt_outlined, // icon: Icon(Icons.filter_alt_outlined,
@ -2302,32 +2258,26 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
// nonChartData Cards // nonChartData Cards
Padding( Padding(
padding: const EdgeInsets.all(3.34), padding: const EdgeInsets.all(3.34),
child: GridView.builder( child: GridView.builder(
key: cardKey, key: cardKey,
itemCount: cardData.length, itemCount: cardData.length,
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
gridDelegate: gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount:crossAxisCount,
// crossAxisCount:2, // crossAxisCount: cardData.length % 2 == 0 ? 2 : 3,
crossAxisCount:
cardData.length % 2 == 0 ? 2 : 3,
// crossAxisCount: cardData.length == 2
// ? 2
// : cardData.length == 3
// ? 3
// : cardData.length == 4
// ? 2
// : 3, // Default to 3 if more than 4 items // 2 cards per row
crossAxisSpacing: 2, crossAxisSpacing: 2,
mainAxisSpacing: 5, mainAxisSpacing: 5,
childAspectRatio: MediaQuery.of(context) childAspectRatio: MediaQuery.of(context)
.size .size
.width / .width /
(MediaQuery.of(context).size.height / (MediaQuery.of(context).size.height /
(cardData.length % 2 == 0 (cardData.length % 2 == 0 ? 2 : 2)),
? 2
: 1.3)),
// childAspectRatio: // childAspectRatio:
// calculateAspectRatio(cardData.length, cardData), // calculateAspectRatio(cardData.length, cardData),
), ),
@ -2366,6 +2316,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
borderRadius: borderRadius:
BorderRadius.circular(12), BorderRadius.circular(12),
border: Border.all( border: Border.all(
color: Color(int.parse( color: Color(int.parse(
(chartScreenData[ (chartScreenData[
'border_color'] ?? 'border_color'] ??
@ -2444,15 +2395,17 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
height: 20.0, height: 20.0,
child: FittedBox( child: FittedBox(
child: Text( child: Text(
'(${response[0]['display_value'] ?? 'NA'})', // '(${response[0]['display_value'] ?? 'NA'})',
// '(${data['firstYear'] ?? RegExp(r'\d').hasMatch(response[0]['display_value'] ?? '')
// 'NA'} - ${data['lastYear'] ?? ? '(${response[0]['display_value'] ?? 'NA'})'
// 'NA'})', : '${response[0]['display_value'] ?? 'NA'}',
style: style:
const TextStyle( const TextStyle(
fontSize: 10, fontSize: 10,
color: Colors color: Colors.grey,
.grey), overflow: TextOverflow.ellipsis,
),
), ),
), ),
), ),
@ -2467,60 +2420,35 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
child: Row( child: Row(
children: [ children: [
Text( Text(
response[0][ response[0]['value'] ?? 'NA',
'value'] ??
'NA',
// '${data['roundedAverage'] ?? // '${data['roundedAverage'] ??
// 'NA'}', // 'NA'}',
style: TextStyle( style:
fontSize: 20, TextStyle(
fontSize: 18,
fontWeight: fontWeight:
FontWeight FontWeight.w800,
.w900, color: response[0]['calculation'] == 'different'
color: response[0] ? _getColorFromHex(response[0]['font_color'])
[ : const Color(0xFF90B0D5),
'calculation'] ==
'different'
? _getColorFromHex(
response[0]
[
'font_color'])
: const Color(
0xFF90B0D5),
// color: Color( // color: Color(
// 0xFF90B0D5), // 0xFF90B0D5),
), ),
), ),
const SizedBox( const SizedBox(width: 1), // Space between text and icon
width: if (response[0]['calculation'] == 'different') ...[
1), // Space between text and icon if (response[0]['font_color'] == '#D83731')
if (response[0][ const Icon(Icons.arrow_downward, color: Colors.red, size: 20)
'calculation'] == else if (response[0]['font_color'] == '#11AF22')
'different') ...[ const Icon(Icons.arrow_upward, color: Colors.green, size: 20),
if (response[0][
'font_color'] ==
'#D83731')
const Icon(
Icons
.arrow_downward,
color: Colors
.red,
size: 22)
else if (response[
0][
'font_color'] ==
'#11AF22')
const Icon(
Icons
.arrow_upward,
color: Colors
.green,
size: 22),
], ],
], ],
),
), ),
), ),
),
), ),
], ],
), ),
@ -2608,12 +2536,16 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
), ),
const SizedBox(height: 1), const SizedBox(height: 1),
Text( Text(
'(${response[0]['display_value'] ?? 'NA'})', // '(${response[0]['display_value'] ?? 'NA'})',
RegExp(r'\d').hasMatch(response[0]['display_value'] ?? '')
? '(${response[0]['display_value'] ?? 'NA'})'
: '${response[0]['display_value'] ?? 'NA'}',
// '(${data['lastYear'] ?? 'NA'})',
style: const TextStyle( style: const TextStyle(
fontSize: 10, fontSize: 10,
color: Colors.grey), color: Colors.grey,
overflow: TextOverflow.ellipsis,),
), ),
const SizedBox(height: 1), const SizedBox(height: 1),
Flexible( Flexible(
@ -2632,14 +2564,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
fontSize: 18, fontSize: 18,
fontWeight: fontWeight:
FontWeight.w900, FontWeight.w900,
color: response[0][ color: response[0]['calculation'] == 'different'
'calculation'] == ? _getColorFromHex(response[0]['font_color'])
'different' : const Color(0xFF90B0D5),
? _getColorFromHex(
response[0][
'font_color'])
: const Color(
0xFF90B0D5),
), ),
), ),
), ),
@ -2666,26 +2593,26 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
fontSize: 14, fontSize: 14,
fontWeight: fontWeight:
FontWeight.w600, FontWeight.w600,
color: response[1][
'calculation'] == color: response[1]['calculation'] == 'different'
'different' ? _getColorFromHex(response[0]['font_color'])
? _getColorFromHex( : const Color(0xFFD83731),
response[0][
'font_color'])
: const Color(
0xFFD83731),
), ),
), ),
), ),
), ),
Text( Text(
'(${response[1]['display_value'] ?? 'NA'})', // '(${response[1]['display_value'] ?? 'NA'})',
// '(${data['secondLastYear'] ?? 'NA'})', RegExp(r'\d').hasMatch(response[1]['display_value'] ?? '')
? '(${response[1]['display_value'] ?? 'NA'})'
: '${response[1]['display_value'] ?? 'NA'}',
style: const TextStyle( style: const TextStyle(
fontSize: 9, fontSize: 9,
fontWeight: fontWeight:
FontWeight.w500, FontWeight.w500,
color: Colors.grey), color: Colors.grey,
overflow: TextOverflow.ellipsis,),
), ),
], ],
), ),

View File

@ -49,34 +49,22 @@ class ChartWidget extends StatelessWidget {
List<PieChartSectionData> parsePieChartData( List<PieChartSectionData> parsePieChartData(
dynamic chartData, dynamic chartData,
double totalValue, double totalValue,
// String totalValue,
int? touchedIndex, int? touchedIndex,
) { ) {
debugPrint('Chart Data: ${jsonEncode(chartData)}'); debugPrint('Chart Data: ${jsonEncode(chartData)}');
return chartData['response'] return chartData['response']
.asMap() .asMap()
.entries .entries
.map<PieChartSectionData>((entry) { .map<PieChartSectionData>((entry) {
int index = entry.key; int index = entry.key;
print('piePArse');
var data = entry.value; var data = entry.value;
// double value = double.tryParse(data['ObsValue']['Value']) ?? 0.0;
// double value = (data['ObsValue']['Value'] is double)
// ? data['ObsValue']['Value']
// : (data['ObsValue']['Value'] is int)
// ? (data['ObsValue']['Value'] as int).toDouble()
// : 0.0;
// Handle different types: int, double, and String // Handle different types: int, double, and String
double value = 0.0; double value = 0.0;
var rawValue = data['ObsValue']['Value']; var rawValue = data['ObsValue']['Value'];
print('Raw Value: $rawValue (Type: ${rawValue.runtimeType})');
if (rawValue is String) { if (rawValue is String) {
value = double.tryParse(rawValue) ?? 0.0; value = double.tryParse(rawValue) ?? 0.0;
} else if (rawValue is int) { } else if (rawValue is int) {
@ -87,24 +75,8 @@ class ChartWidget extends StatelessWidget {
print('Unexpected Type for ObsValue[Value]: ${rawValue.runtimeType}'); print('Unexpected Type for ObsValue[Value]: ${rawValue.runtimeType}');
} }
// if (data['ObsValue']['Value'] is String) {
// value = double.tryParse(data['ObsValue']['Value']) ?? 0.0; // Parse string to double
// } else if (data['ObsValue']['Value'] is int) {
// value = (data['ObsValue']['Value'] as int).toDouble(); // Convert int to double
// } else if (data['ObsValue']['Value'] is double) {
// value = data['ObsValue']['Value']; // Already a double
// }
print('piePArse1 - $value');
// double percentage = (value / totalValue) * 100; // double percentage = (value / totalValue) * 100;
double percentage = (totalValue > 0) ? (value / totalValue) * 100 : 0.0; double percentage = (totalValue > 0) ? (value / totalValue) * 100 : 0.0;
if (kDebugMode) {
print('percentage- $percentage');
print('Total Value: $totalValue');
}
debugPrint('debug Total Value- $totalValue');
debugPrint('debug percentage- $percentage');
bool isTouched = index == touchedIndex; bool isTouched = index == touchedIndex;
return PieChartSectionData( return PieChartSectionData(
@ -119,9 +91,11 @@ class ChartWidget extends StatelessWidget {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.black, color: Colors.black,
// color: Colors.white, // color: Colors.white,
), ),
titlePositionPercentageOffset: 1.3, titlePositionPercentageOffset: 1.3,
); );
}).toList(); }).toList();
} }
@ -150,32 +124,28 @@ class ChartWidget extends StatelessWidget {
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blueGrey[800], // Change background color color: Colors.blueGrey[800], // Change background color
borderRadius: borderRadius: BorderRadius.circular(8), // Optional: rounded corners
BorderRadius.circular(8), // Optional: rounded corners
), ),
textStyle: TextStyle(color: Colors.white), // Change text color textStyle: TextStyle(color: Colors.white), // Change text color
), ),
child: Tooltip( child: Tooltip(
message: title, // Full text on hover message: title, // Full text on hover
child: ConstrainedBox( child: ConstrainedBox( // Constrain width to allow wrapping
// Constrain width to allow wrapping
constraints: BoxConstraints(maxWidth: 100), constraints: BoxConstraints(maxWidth: 100),
child: Text( child: Text(
title, title,
style: TextStyle( style: TextStyle(fontSize: 12,),
fontSize: 12,
),
softWrap: true, softWrap: true,
maxLines: 2, maxLines: 2,
overflow: overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
TextOverflow.ellipsis, // Ensures text doesn't overflow
),
),
), ),
), ),
),),
SizedBox(width: 5), SizedBox(width: 5),
], ],
); );
}).toList(); }).toList();
} }
@ -287,28 +257,12 @@ class ChartWidget extends StatelessWidget {
), ),
); );
case 'pie_chart': case 'pie_chart':
double totalValue = chartData['response'].map<double>((entry) { double totalValue = chartData['response']
.map<double>((entry) {
var value = entry['ObsValue']['Value']; var value = entry['ObsValue']['Value'];
print( // print('Processing value: $value, type: ${value.runtimeType}');
'Processing value: $value, type: ${value.runtimeType}'); // Debug each value return (value is num) ? value.toDouble() : value is String ? double.tryParse(value) ?? 0.0 : 0.0;
print(value is int
? value.toDouble()
: value is String
? double.tryParse(value) ?? 0.0
: 0.0);
return (value is num)
? value.toDouble()
: value is String
? double.tryParse(value) ?? 0.0
: 0.0;
}).fold(0.0, (prev, element) => prev + element); }).fold(0.0, (prev, element) => prev + element);
// List<String> totalValues = chartData['response']
// .map<String>((entry) {
// var value = entry['ObsValue']['Value'];
// print('Processing value: $value, type: ${value.runtimeType}'); // Debug each value
//
// return value.toString(); // Convert to string
// }).fold(0.0, (prev, element) => prev + element);
ValueNotifier<int?> touchedIndex = ValueNotifier(null); ValueNotifier<int?> touchedIndex = ValueNotifier(null);
@ -324,6 +278,7 @@ class ChartWidget extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 15), SizedBox(height: 15),
Text( Text(
chartData['chart_sub_heading'] ?? '', chartData['chart_sub_heading'] ?? '',
style: TextStyle( style: TextStyle(
@ -333,6 +288,7 @@ class ChartWidget extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 70), SizedBox(height: 70),
Expanded( Expanded(
child: ValueListenableBuilder<int?>( child: ValueListenableBuilder<int?>(
valueListenable: touchedIndex, valueListenable: touchedIndex,
@ -355,13 +311,16 @@ class ChartWidget extends StatelessWidget {
null; // Reset when not touching null; // Reset when not touching
} }
}, },
), ),
), ),
); );
}, },
), ),
), ),
SizedBox(height: 65), SizedBox(height:105),
Flexible( Flexible(
// child: SingleChildScrollView( // child: SingleChildScrollView(
// scrollDirection: Axis.horizontal, // scrollDirection: Axis.horizontal,
@ -434,11 +393,11 @@ class ChartWidget extends StatelessWidget {
fitInsideHorizontally: true, fitInsideHorizontally: true,
fitInsideVertically: true, fitInsideVertically: true,
// tooltipPadding: const EdgeInsets.all(8), // tooltipPadding: const EdgeInsets.all(8),
tooltipPadding: const EdgeInsets.symmetric( tooltipPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8), // Optional
horizontal: 4, vertical: 8), // Optional
tooltipHorizontalAlignment: FLHorizontalAlignment.left, tooltipHorizontalAlignment: FLHorizontalAlignment.left,
tooltipMargin: 16, tooltipMargin: 16,
getTooltipItem: getTooltipItem:
(groupData, groupIndex, rodData, rodIndex) { (groupData, groupIndex, rodData, rodIndex) {
// Get the list of group names dynamically // Get the list of group names dynamically
@ -633,9 +592,10 @@ class ChartWidget extends StatelessWidget {
// (entry) => double.parse(entry['ObsKey']['TIME_PERIOD'])) // (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']))
// .toSet(); // .toSet();
Set<String> uniqueXValues = filteredData.map<String>((entry) {
String? timePeriod = Set<String> uniqueXValues = filteredData
entry['ObsKey']['TIME_PERIOD']; // Nullable String .map<String>((entry) {
String? timePeriod = entry['ObsKey']['TIME_PERIOD']; // Nullable String
print('TIME_PERIOD- $timePeriod'); print('TIME_PERIOD- $timePeriod');
if (timePeriod == null) { if (timePeriod == null) {
@ -657,7 +617,8 @@ class ChartWidget extends StatelessWidget {
print('Unknown format: $timePeriod'); print('Unknown format: $timePeriod');
return timePeriod; // Keep it as is return timePeriod; // Keep it as is
} }
}).toSet(); })
.toSet();
print("Unique X Values: $uniqueXValues"); print("Unique X Values: $uniqueXValues");
@ -666,30 +627,18 @@ class ChartWidget extends StatelessWidget {
if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) { if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) {
return double.parse(timePeriod); // Year-only (2019 2019.0) return double.parse(timePeriod); // Year-only (2019 2019.0)
} else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) { } else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) {
return double.parse(timePeriod.replaceAll( return double.parse(timePeriod.replaceAll('-', '.')); // Year-Month (2019-11 2019.11)
'-', '.')); // Year-Month (2019-11 2019.11)
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
// Year-MonthAbbr (2019-Nov) // Year-MonthAbbr (2019-Nov)
Map<String, int> monthMap = { Map<String, int> monthMap = {
'Jan': 1, 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
'Feb': 2, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
'Mar': 3, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
'Apr': 4,
'May': 5,
'Jun': 6,
'Jul': 7,
'Aug': 8,
'Sep': 9,
'Oct': 10,
'Nov': 11,
'Dec': 12
}; };
List<String> parts = timePeriod.split('-'); List<String> parts = timePeriod.split('-');
int month = int month = monthMap[parts[1]] ?? 1; // Default to January if unknown
monthMap[parts[1]] ?? 1; // Default to January if unknown return double.parse('${parts[0]}.$month'); // Convert to format (2019-Nov 2019.11)
return double.parse(
'${parts[0]}.$month'); // Convert to format (2019-Nov 2019.11)
} }
throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
@ -701,12 +650,15 @@ class ChartWidget extends StatelessWidget {
.toSet(); .toSet();
print('Processed X Values: $uniqueXValuesProcessed'); print('Processed X Values: $uniqueXValuesProcessed');
print('LnTrnd2.1'); print('LnTrnd2.1');
// Generate line bars for the chart // Generate line bars for the chart
List<LineChartBarData> lineBars = List<LineChartBarData> lineBars =
lineBarsData(filteredData, groupByValues, groupByKey); lineBarsData(filteredData, groupByValues, groupByKey);
print('LnTrnd3'); print('LnTrnd3');
return Column(children: [ return Column(children: [
@ -730,6 +682,7 @@ class ChartWidget extends StatelessWidget {
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
child: LineChart(LineChartData( child: LineChart(LineChartData(
lineTouchData: lineTouchData1(), lineTouchData: lineTouchData1(),
gridData: gridData(), gridData: gridData(),
@ -739,10 +692,12 @@ class ChartWidget extends StatelessWidget {
lineBarsData: lineBars, lineBarsData: lineBars,
// minX: uniqueXValues.reduce((a, b) => a < b ? a : b), // minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
// maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), // maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
// minX: uniqueXValuesProcessed.reduce((a, b) => a < b ? a : b), // minX: uniqueXValuesProcessed.reduce((a, b) => a < b ? a : b),
// maxX: uniqueXValuesProcessed.reduce((a, b) => a > b ? a : b), // maxX: uniqueXValuesProcessed.reduce((a, b) => a > b ? a : b),
))), ))
),
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Wrap( child: Wrap(
@ -991,6 +946,7 @@ class ChartWidget extends StatelessWidget {
// Extract groupBy values and their corresponding y-axis values // Extract groupBy values and their corresponding y-axis values
List<String> xAxisData = []; List<String> xAxisData = [];
List<double> yAxisData = []; List<double> yAxisData = [];
List<String> yAxisLabels = [];
var xadditionalgrp= chartData['chart_type_json']['additional_x_group']; var xadditionalgrp= chartData['chart_type_json']['additional_x_group'];
@ -999,9 +955,9 @@ class ChartWidget extends StatelessWidget {
for (var entry in chartData['response']) { for (var entry in chartData['response']) {
var xValue = entry['ObsKey'][groupByKey]; var xValue = entry['ObsKey'][groupByKey];
var xTimePeriod= entry['ObsKey']['TIME_PERIOD']; var xTimePeriod= entry['ObsKey']['TIME_PERIOD'];
var unitMsr = entry['ObsKey']['UNIT_MEASURE'];
var yValue = entry['ObsValue']['Value']; var yValue = entry['ObsValue']['Value'];
var xadditionalgroup = var xadditionalgroup= chartData['chart_type_json']['additional_x_group'];
chartData['chart_type_json']['additional_x_group'];
print('chartData response: ${chartData['response']}'); print('chartData response: ${chartData['response']}');
@ -1009,22 +965,18 @@ class ChartWidget extends StatelessWidget {
print('Xadditionalt-$xTimePeriod'); print('Xadditionalt-$xTimePeriod');
print('xadditionalgroup-$xadditionalgroup'); print('xadditionalgroup-$xadditionalgroup');
print('yValue-$yValue'); print('yValue-$yValue');
print('unitMsr-$unitMsr');
if (xadditionalgrp == 'TIME_PERIOD') { if (xadditionalgrp == 'TIME_PERIOD') {
chartData['response'].sort((a, b) { chartData['response'].sort((a, b) {
// Convert TIME_PERIOD to int for proper sorting // Convert TIME_PERIOD to int for proper sorting
int timeA = int timeA = int.tryParse(a['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
int.tryParse(a['ObsKey']['TIME_PERIOD'].toString()) ?? 0; int timeB = int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
int timeB =
int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
// Extract QUARTER and convert "Q1", "Q2", etc. to numeric values // Extract QUARTER and convert "Q1", "Q2", etc. to numeric values
int quarterA = int.tryParse( int quarterA = int.tryParse(a['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? 0;
a['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? int quarterB = int.tryParse(b['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? 0;
0;
int quarterB = int.tryParse(
b['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ??
0;
// First, sort by TIME_PERIOD. If equal, sort by QUARTER // First, sort by TIME_PERIOD. If equal, sort by QUARTER
if (timeA != timeB) { if (timeA != timeB) {
@ -1047,8 +999,12 @@ class ChartWidget extends StatelessWidget {
} }
xAxisData.add(xLabel); xAxisData.add(xLabel);
yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
yAxisLabels.add(unitMsr ?? '');
} }
} }
return Column(children: [ return Column(children: [
Text( Text(
@ -1077,6 +1033,8 @@ class ChartWidget extends StatelessWidget {
maxY: yAxisData.isNotEmpty maxY: yAxisData.isNotEmpty
? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2 ? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2
: 10, : 10,
// barTouchData: BarTouchData(enabled: true), // barTouchData: BarTouchData(enabled: true),
barTouchData: BarTouchData( barTouchData: BarTouchData(
enabled: true, enabled: true,
@ -1087,8 +1045,13 @@ class ChartWidget extends StatelessWidget {
// tooltipPadding: const EdgeInsets.all(8), // tooltipPadding: const EdgeInsets.all(8),
// tooltipMargin: 16, // tooltipMargin: 16,
getTooltipItem: (group, groupIndex, rod, rodIndex) { getTooltipItem: (group, groupIndex, rod, rodIndex) {
String unitMsrLabel = yAxisLabels.isNotEmpty && groupIndex < yAxisLabels.length
? yAxisLabels[groupIndex]
: '';
return BarTooltipItem( return BarTooltipItem(
rod.toY.toStringAsFixed(1), '${rod.toY.toStringAsFixed(1)}\n$unitMsrLabel',
const TextStyle(color: Colors.white), const TextStyle(color: Colors.white),
); );
}, },
@ -1122,8 +1085,7 @@ class ChartWidget extends StatelessWidget {
: title; : title;
return Padding( return Padding(
padding: padding: const EdgeInsets.only(top: 8.0,left: 55.0),
const EdgeInsets.only(top: 8.0, left: 55.0),
child: SizedBox( child: SizedBox(
width: 60, // Limit width to force wrapping width: 60, // Limit width to force wrapping
child: Transform.rotate( child: Transform.rotate(
@ -1133,41 +1095,34 @@ class ChartWidget extends StatelessWidget {
child: TooltipTheme( child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blueGrey[ color: Colors.blueGrey[800], // Change background color
800], // Change background color borderRadius: BorderRadius.circular(8), // Optional: rounded corners
borderRadius: BorderRadius.circular(
8), // Optional: rounded corners
), ),
textStyle: TextStyle( textStyle: TextStyle(color: Colors.white), // Change text color
color: Colors
.white), // Change text color
), ),
child: TooltipTheme( child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blueGrey[ color: Colors.blueGrey[800], // Change background color
800], // Change background color borderRadius: BorderRadius.circular(8), // Optional: rounded corners
borderRadius: BorderRadius.circular(
8), // Optional: rounded corners
), ),
textStyle: TextStyle( textStyle: TextStyle(color: Colors.white), // Change text color
color: Colors
.white), // Change text color
), ),
child: Tooltip( child: Tooltip(
message: title, message: title,
child: Text( child: Text(
// title, // title,
displayTitle, displayTitle,
softWrap: true, softWrap: true,
style: TextStyle( style: TextStyle(fontSize: 10,),
fontSize: 10,
),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
),),
), ),
), ),
),
),
))); )));
} }
return Container(); return Container();
@ -1308,8 +1263,7 @@ class ChartWidget extends StatelessWidget {
), ),
), ),
topTitles: AxisTitles( topTitles: AxisTitles(
sideTitles: sideTitles: SideTitles(showTitles: false), // Hide top titles
SideTitles(showTitles: false), // Hide top titles
), ),
rightTitles: AxisTitles( rightTitles: AxisTitles(
sideTitles: sideTitles:
@ -1333,8 +1287,7 @@ class ChartWidget extends StatelessWidget {
), ),
), ),
), ),
), ),),
),
]); ]);
case 'fl_multi_bar': case 'fl_multi_bar':
double _calculateChartWidth(dynamic chartData) { double _calculateChartWidth(dynamic chartData) {
@ -1346,10 +1299,14 @@ class ChartWidget extends StatelessWidget {
// Group crops by CROP_TYPE // Group crops by CROP_TYPE
Map<String, List<String>> groupedCrops = {}; Map<String, List<String>> groupedCrops = {};
int touchedGroupIndex = -1; int touchedGroupIndex = -1;
// Iterate over the chartData to group crops by CROP_TYPE // Iterate over the chartData to group crops by CROP_TYPE
for (var item in chartData['response']) { for (var item in chartData['response']) {
print("MultiBArRaw item: $item"); print("MultiBArRaw item: $item");
String crop = item['ObsKey'][cropKey]; String crop = item['ObsKey'][cropKey];
@ -1357,8 +1314,7 @@ class ChartWidget extends StatelessWidget {
// Use a Set to avoid duplicates // Use a Set to avoid duplicates
if (groupedCrops.containsKey(cropType)) { if (groupedCrops.containsKey(cropType)) {
groupedCrops[cropType] = groupedCrops[cropType] = (groupedCrops[cropType]! + [crop]).toSet().toList();
(groupedCrops[cropType]! + [crop]).toSet().toList();
} else { } else {
groupedCrops[cropType] = [crop]; groupedCrops[cropType] = [crop];
} }
@ -1380,6 +1336,7 @@ class ChartWidget extends StatelessWidget {
// //
// print('groupedCropsflmutli- $groupedCrops'); // print('groupedCropsflmutli- $groupedCrops');
return Center( return Center(
child: Column(children: [ child: Column(children: [
Text( Text(
@ -1410,8 +1367,8 @@ class ChartWidget extends StatelessWidget {
child: BarChart( child: BarChart(
BarChartData( BarChartData(
alignment: BarChartAlignment.spaceAround, alignment: BarChartAlignment.spaceAround,
maxY: _calculateMaxY( maxY:
chartData), // Dynamically calculate max Y _calculateMaxY(chartData), // Dynamically calculate max Y
barGroups: _buildHorizontalRotateBarGroups( barGroups: _buildHorizontalRotateBarGroups(
chartData, groupByValues), // Build bar groups chartData, groupByValues), // Build bar groups
titlesData: FlTitlesData( titlesData: FlTitlesData(
@ -1434,21 +1391,16 @@ class ChartWidget extends StatelessWidget {
return Padding( return Padding(
padding: const EdgeInsets.only(top: 8.0), padding: const EdgeInsets.only(top: 8.0),
child: SizedBox( child: SizedBox(
width: width: 60, // Limit width to force wrapping
60, // Limit width to force wrapping
child: Transform.rotate( child: Transform.rotate(
angle: -0.5, angle: -0.5,
child: TooltipTheme( child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blueGrey[ color: Colors.blueGrey[800], // Change background color
800], // Change background color borderRadius: BorderRadius.circular(8), // Optional: rounded corners
borderRadius: BorderRadius.circular(
8), // Optional: rounded corners
), ),
textStyle: TextStyle( textStyle: TextStyle(color: Colors.white), // Change text color
color: Colors
.white), // Change text color
), ),
child: Tooltip( child: Tooltip(
message: title, message: title,
@ -1458,6 +1410,7 @@ class ChartWidget extends StatelessWidget {
// style: TextStyle(backgroundColor: Colors.blueGrey[800]), // style: TextStyle(backgroundColor: Colors.blueGrey[800]),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
)), )),
), ),
))); )));
// return Transform.rotate( // return Transform.rotate(
@ -1481,8 +1434,7 @@ class ChartWidget extends StatelessWidget {
borderData: FlBorderData(show: false), borderData: FlBorderData(show: false),
barTouchData: BarTouchData( barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
tooltipHorizontalAlignment: tooltipHorizontalAlignment: FLHorizontalAlignment.center,
FLHorizontalAlignment.center,
tooltipRoundedRadius: 8, tooltipRoundedRadius: 8,
fitInsideHorizontally: fitInsideHorizontally:
true, // Ensure it fits within the screen true, // Ensure it fits within the screen
@ -1500,8 +1452,7 @@ class ChartWidget extends StatelessWidget {
groupByValues.elementAt(groupIndex); groupByValues.elementAt(groupIndex);
// Fetch the crop for the current group from groupedCrops // Fetch the crop for the current group from groupedCrops
String cropType = String cropType = groupByValues.elementAt(groupIndex);
groupByValues.elementAt(groupIndex);
print('GrpcropType: $cropType'); print('GrpcropType: $cropType');
// String crop = groupedCrops[cropType]![rodIndex]; // String crop = groupedCrops[cropType]![rodIndex];
@ -1514,9 +1465,7 @@ class ChartWidget extends StatelessWidget {
print( print(
'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex'); 'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex');
// crop = cropType; // Fallback to cropType // crop = cropType; // Fallback to cropType
crop = (crops != null && crops.isNotEmpty) crop = (crops != null && crops.isNotEmpty) ? crops.first : cropType;
? crops.first
: cropType;
} }
// print('groupedCrops1: $groupedCrops - $rodIndex'); // print('groupedCrops1: $groupedCrops - $rodIndex');
@ -1563,8 +1512,7 @@ class ChartWidget extends StatelessWidget {
response != null && response != null &&
response.spot != null) { response.spot != null) {
// setState(() { // setState(() {
touchedGroupIndex = touchedGroupIndex = response.spot!.touchedBarGroupIndex;
response.spot!.touchedBarGroupIndex;
// }); // });
} else { } else {
// setState(() { // setState(() {
@ -1607,10 +1555,10 @@ class ChartWidget extends StatelessWidget {
int numberOfBars = int numberOfBars =
groupedCrops.length; // Number of grouped sets (bar groups) groupedCrops.length; // Number of grouped sets (bar groups)
double barHeight = 40.0; // Height per individual bar double barHeight = 10.0; // Height per individual bar
double barSpacing = 30.0; // Space between bar sets double barSpacing = 1.0; // Space between bar sets
double minHeight = 300.0; // Minimum chart height double minHeight = 300.0; // Minimum chart height
double maxHeight = 1000.0; // Maximum chart height double maxHeight = 500.0; // Maximum chart height
// Calculate total height dynamically // Calculate total height dynamically
double chartHeight = double chartHeight =
@ -1629,6 +1577,7 @@ class ChartWidget extends StatelessWidget {
SizedBox(height: 5), SizedBox(height: 5),
Text( Text(
chartData['chart_sub_heading'] ?? '', chartData['chart_sub_heading'] ?? '',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300,
@ -1640,22 +1589,24 @@ class ChartWidget extends StatelessWidget {
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: SingleChildScrollView( // child: SingleChildScrollView(
scrollDirection: Axis.horizontal, // scrollDirection: Axis.horizontal,
child: SizedBox( child: SizedBox(
width: 1000, // width: 500,
// width: 1000,
height: chartHeight, height: chartHeight,
child: BarChart( child: Stack(
children: [
BarChart(
BarChartData( BarChartData(
maxY: 400000, maxY: 400000,
rotationQuarterTurns: rotationTurns, rotationQuarterTurns: rotationTurns,
barTouchData: BarTouchData( barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
tooltipHorizontalAlignment: tooltipHorizontalAlignment: FLHorizontalAlignment.center,
FLHorizontalAlignment.center,
tooltipRoundedRadius: 8, tooltipRoundedRadius: 8,
fitInsideHorizontally: fitInsideHorizontally: true, // Ensure it fits within the screen
true, // Ensure it fits within the screen
fitInsideVertically: true, fitInsideVertically: true,
tooltipPadding: EdgeInsets.all(8), tooltipPadding: EdgeInsets.all(8),
tooltipMargin: 16, tooltipMargin: 16,
@ -1728,21 +1679,24 @@ class ChartWidget extends StatelessWidget {
titlesData: FlTitlesData( titlesData: FlTitlesData(
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: false, // showTitles: false,
reservedSize: 20, reservedSize: 40,
interval: 100000, interval: 100000,
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
return Text( return SizedBox(
width: 50,
child: Text(
value.toInt().toString(), value.toInt().toString(),
style: const TextStyle(fontSize: 12), textAlign: TextAlign.justify,
); style: const TextStyle(fontSize: 12,),
),);
}, },
), ),
), ),
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
reservedSize: 80, // Added space for rotated titles reservedSize: 150, // Added space for rotated titles
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
if (value < groupByValues.length) { if (value < groupByValues.length) {
String title = String title =
@ -1752,9 +1706,10 @@ class ChartWidget extends StatelessWidget {
-1.58, // Rotation in radians (~ -30 degrees) -1.58, // Rotation in radians (~ -30 degrees)
child: Center( child: Center(
child: SizedBox( child: SizedBox(
width: 80, width: 120,
child: Text( child: Text(
title, title,
textAlign: TextAlign.end,
style: const TextStyle(fontSize: 12), style: const TextStyle(fontSize: 12),
softWrap: true, softWrap: true,
maxLines: 2, maxLines: 2,
@ -1802,191 +1757,13 @@ class ChartWidget extends StatelessWidget {
alignment: BarChartAlignment.spaceAround, alignment: BarChartAlignment.spaceAround,
), ),
), ),
])
), ),
),
// ),
)), )),
// Expanded(
// child: Stack(
// children:[
// BarChart(
// BarChartData(
// maxY: 400000,
// rotationQuarterTurns: rotationTurns,
// barTouchData: BarTouchData(
// touchTooltipData: BarTouchTooltipData(
// tooltipHorizontalAlignment: FLHorizontalAlignment.center,
// // Only show tooltip when touched
// getTooltipItem: (group, groupIndex, rod, rodIndex) {
// if (rod.toY == 0 || touchedGroupIndex == -1) {
// return null; // Don't show the tooltip if the value is 0 or there's no touch
// }
//
// if (groupIndex == touchedGroupIndex) {
// // print('Group Index: $groupIndex, Group : $group');
//
// // Get the group label dynamically
// String groupLabel = groupByValues.elementAt(groupIndex);
//
// // Fetch the crop for the current group from groupedCrops
// String cropType = groupByValues.elementAt(groupIndex);
// String crop = groupedCrops[cropType]![rodIndex];
// double value = rod.toY;
//
// String formattedValue;
// if (value >= 1000000) {
// formattedValue =
// (value / 1000000).toStringAsFixed(1) + 'M';
// } else if (value >= 1000) {
// formattedValue =
// (value / 1000).toStringAsFixed(1) + 'K';
// } else {
// formattedValue = value
// .toStringAsFixed(0); // for values smaller than 1000
// }
//
// return BarTooltipItem(
// '$groupLabel\n$crop',
// const TextStyle(
// color: Colors.white,
// fontWeight: FontWeight.bold,
// ),
// children: [
// TextSpan(
// text: ' Value: $formattedValue',
// style: const TextStyle(
// color: Colors.yellow,
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// );
// }
// return null;
// },
// ),
// touchCallback: (event, response) {
// if (event.isInterestedForInteractions &&
// response != null &&
// response.spot != null) {
// // setState(() {
// touchedGroupIndex = response.spot!.touchedBarGroupIndex;
// // });
// } else {
// // setState(() {
// touchedGroupIndex = -1; // Reset if no interaction
// // });
// }
// },
// ),
// titlesData: FlTitlesData(
// leftTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: false,
// reservedSize: 20,
// interval: 100000,
// getTitlesWidget: (value, meta) {
// return Text(
// value.toInt().toString(),
// style: const TextStyle(fontSize: 12),
// );
// },
// ),
// ),
// bottomTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: true,
// reservedSize: 80, // Added space for rotated titles
// getTitlesWidget: (value, meta) {
// if (value < groupByValues.length) {
// String title = groupByValues.elementAt(value.toInt());
// return Transform.rotate(
// angle: -1.58, // Rotation in radians (~ -30 degrees)
// child: Center(
// child: SizedBox(
// width: 80,
// child: Text(
// title,
// style: const TextStyle(fontSize: 12),
// softWrap: true,
// maxLines: 2,
// ),
// ),
// ),
// );
// }
// return const SizedBox.shrink();
// },
// ),
// ),
// rightTitles:
// AxisTitles(sideTitles: SideTitles(showTitles: false)),
// topTitles:
// AxisTitles(sideTitles: SideTitles(showTitles: false)),
// ),
// borderData: FlBorderData(
// show: true,
// border: const Border(
// // left: BorderSide(color: Colors.grey),
// bottom: BorderSide(color: Colors.white),
// ),
// ),
// gridData: FlGridData(
// show: false,
// drawVerticalLine: true,
// verticalInterval: 1,
// horizontalInterval: 100000,
// getDrawingHorizontalLine: (value) {
// return FlLine(
// color: Colors.grey.withOpacity(0.5),
// strokeWidth: 1,
// );
// },
// getDrawingVerticalLine: (value) {
// return FlLine(
// color: Colors.grey.withOpacity(0.5),
// strokeWidth: 1,
// );
// },
// ),
// barGroups:
// _buildHorizontalRotateBarGroups(chartData, groupByValues),
// alignment: BarChartAlignment.spaceAround,
// ),
//
// ),
// // Overlay Texts
// ..._buildHorizontalRotateBarGroups(chartData, groupByValues)
// .asMap()
// .entries
// .expand((entry) {
// int groupIndex = entry.key;
// BarChartGroupData groupData = entry.value;
// return groupData.barRods.asMap().entries.map((rodEntry) {
// int rodIndex = rodEntry.key;
// BarChartRodData rodData = rodEntry.value;
//
// // Position calculation
// double barHeight = rodData.toY / 400000 * MediaQuery.of(context).size.height;
//
// return Positioned(
// left: (groupIndex * 80).toDouble() + 20, // Adjust based on spacing
// bottom: barHeight / 2, // Centered inside the bar
// child: Transform.rotate(
// angle: -0.1,
// child: Text(
// // '${rodData.toY.toInt()}',
// "123",
// style: TextStyle(
// color: Colors.black,
// fontWeight: FontWeight.bold,
// fontSize: 12,
// ),
// ),
// ),
// );
// }).toList();
// }).toList(),
// ]))
]); ]);
default: default:
@ -2083,6 +1860,7 @@ class ChartWidget extends StatelessWidget {
return lineBars; return lineBars;
} }
/// Function to parse TIME_PERIOD into a EXACT value /// Function to parse TIME_PERIOD into a EXACT value
double parseTimePeriod(String timePeriod) { double parseTimePeriod(String timePeriod) {
// Match formats // Match formats
@ -2091,23 +1869,13 @@ class ChartWidget extends StatelessWidget {
return double.parse(timePeriod); // Year as a double (2020 2020.0) return double.parse(timePeriod); // Year as a double (2020 2020.0)
} else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) { } else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) {
// Format: Year-Month (e.g., "2020-10") // Format: Year-Month (e.g., "2020-10")
return double.parse( return double.parse(timePeriod.replaceAll('-', '.')); // Convert "2020-10" 2020.10
timePeriod.replaceAll('-', '.')); // Convert "2020-10" 2020.10
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
// Format: Year-MonthAbbr (e.g., "2020-Oct") // Format: Year-MonthAbbr (e.g., "2020-Oct")
Map<String, int> monthMap = { Map<String, int> monthMap = {
'Jan': 1, 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
'Feb': 2, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
'Mar': 3, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
'Apr': 4,
'May': 5,
'Jun': 6,
'Jul': 7,
'Aug': 8,
'Sep': 9,
'Oct': 10,
'Nov': 11,
'Dec': 12
}; };
List<String> parts = timePeriod.split('-'); List<String> parts = timePeriod.split('-');
@ -2119,6 +1887,7 @@ class ChartWidget extends StatelessWidget {
throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
} }
List<LineChartBarData> lineBarsData(List<dynamic> filteredData, List<LineChartBarData> lineBarsData(List<dynamic> filteredData,
Set<String> groupByValues, String groupByKey) { Set<String> groupByValues, String groupByKey) {
List<LineChartBarData> lineBars = []; List<LineChartBarData> lineBars = [];
@ -2183,6 +1952,9 @@ class ChartWidget extends StatelessWidget {
print('spots - $spots'); print('spots - $spots');
// List<FlSpot> spots = filteredData // List<FlSpot> spots = filteredData
// .where((entry) => entry['ObsKey'][groupByKey] == group) // .where((entry) => entry['ObsKey'][groupByKey] == group)
// .map<FlSpot>((entry) { // .map<FlSpot>((entry) {
@ -2198,6 +1970,8 @@ class ChartWidget extends StatelessWidget {
// return FlSpot(xValue, yValue); // return FlSpot(xValue, yValue);
// }).toList(); // }).toList();
print('lineGrp2'); print('lineGrp2');
// Add a line for this group // Add a line for this group
lineBars.add( lineBars.add(
@ -2207,7 +1981,9 @@ class ChartWidget extends StatelessWidget {
color: groupColorMap[group], color: groupColorMap[group],
barWidth: 3, barWidth: 3,
isStrokeCapRound: true, isStrokeCapRound: true,
dotData: FlDotData(show: true),
belowBarData: BarAreaData(show: false), belowBarData: BarAreaData(show: false),
), ),
); );
} }
@ -2242,11 +2018,11 @@ class ChartWidget extends StatelessWidget {
} }
FlTitlesData titlesData1(Set<double> xValues) { FlTitlesData titlesData1(Set<double> xValues) {
print('tileDATa1xvalue - $xValues'); print('tileDATa1xvalue - $xValues');
double findClosest(double value, Set<double> values) { double findClosest(double value, Set<double> values) {
return values return values.reduce((a, b) => (value - a).abs() < (value - b).abs() ? a : b);
.reduce((a, b) => (value - a).abs() < (value - b).abs() ? a : b);
} }
return FlTitlesData( return FlTitlesData(
@ -2262,13 +2038,15 @@ class ChartWidget extends StatelessWidget {
// Check if the value is in the millions or thousands range // Check if the value is in the millions or thousands range
if (value >= 1000000000000) { if (value >= 1000000000000) {
formattedValue = formattedValue = '${(value / 1000000000000).toStringAsFixed(0)}T';
'${(value / 1000000000000).toStringAsFixed(0)}T'; }
} else if (value >= 1000000000) { else if (value >= 1000000000) {
formattedValue = '${(value / 1000000000).toStringAsFixed(0)}B'; formattedValue = '${(value / 1000000000).toStringAsFixed(0)}B';
} else if (value >= 1000000) { }
else if (value >= 1000000) {
formattedValue = '${(value / 1000000).toStringAsFixed(0)}M'; formattedValue = '${(value / 1000000).toStringAsFixed(0)}M';
} else if (value >= 1000) { }
else if (value >= 1000) {
formattedValue = '${(value / 1000).toStringAsFixed(0)}k'; formattedValue = '${(value / 1000).toStringAsFixed(0)}k';
} else { } else {
formattedValue = value.toStringAsFixed( formattedValue = value.toStringAsFixed(
@ -2300,11 +2078,14 @@ class ChartWidget extends StatelessWidget {
interval: null, interval: null,
// interval: 10, // Ensure each year is shown only once // interval: 10, // Ensure each year is shown only once
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
print('BtmTiles :-$value'); print('BtmTiles :-$value');
print('BtmTilesmeta :-$meta'); print('BtmTilesmeta :-$meta');
// if (xValues.contains(value)) // if (xValues.contains(value))
double closestValue = findClosest(value, xValues); double closestValue = findClosest(value, xValues);
if ((closestValue - value).abs() < 0.15) { if ((closestValue - value).abs() < 0.15)
{
print("Bottomtiles"); print("Bottomtiles");
print(value); print(value);
return Padding( return Padding(
@ -2430,8 +2211,7 @@ class ChartWidget extends StatelessWidget {
width: 20, width: 20,
// width: barWidth, // width: barWidth,
borderRadius: BorderRadius.zero, borderRadius: BorderRadius.zero,
color: Colors color: Colors.black// This will act as a container for stacked items
.transparent, // This will act as a container for stacked items
), ),
], ],
); );
@ -2596,6 +2376,7 @@ class ChartWidget extends StatelessWidget {
toY: value, // Use the parsed value toY: value, // Use the parsed value
color: barColor, // Dynamic color color: barColor, // Dynamic color
width: 20, width: 20,
// backDrawRodData: BackgroundBarChartRodData( // backDrawRodData: BackgroundBarChartRodData(
// show: true, // show: true,
// toY: 400000, // toY: 400000,
@ -2626,6 +2407,7 @@ class ChartWidget extends StatelessWidget {
} }
} }
double calculateBarWidth(BuildContext context, int totalBars) { double calculateBarWidth(BuildContext context, int totalBars) {
double width = MediaQuery.of(context).size.width; // Chart width double width = MediaQuery.of(context).size.width; // Chart width
double padding = 16.0; // Space between bars double padding = 16.0; // Space between bars