diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index 2111236f..9a302399 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1346,10 +1346,9 @@ class _ChartScreen1State extends ConsumerState { // If chartFilteredData is empty, print the message if (chartFilteredData.isEmpty) { if (kDebugMode) { - print( - "Selected year: ${selectedFilters.firstWhere((f) => f['filter_key'] == 'TIME_PERIOD', orElse: () => { - 'filter_data': ['Unknown'] - })['filter_data']} - No data for chart: : $chartHeading"); + print("Selected year: ${selectedFilters.firstWhere((f) => f['filter_key'] == 'TIME_PERIOD', + orElse: () => {'filter_data': ['Unknown']})['filter_data']} - No data for chart: : $chartHeading"); + } // Add the complete chart data to the filteredData list @@ -1372,6 +1371,7 @@ class _ChartScreen1State extends ConsumerState { addedChartIds .add(chart['chart_heading']); // Track by a unique identifier } + } // List filteredCardData = []; @@ -1799,18 +1799,21 @@ class _ChartScreen1State extends ConsumerState { print("FilteringDAtss START1 - $filterData"); print('TABId1 - $tabId'); - // for (var item in filterData) { - // if (item['filter_key'] == 'TIME_PERIOD') { - // // Convert the values to integers, sort them, and convert back to strings - // List timePeriodData = item['filter_data'] - // .map((e) => int.parse(e.toString())) // Convert to int - // .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(); - // } - // } + + for (var item in filterData) { + if (item['filter_key'] == 'TIME_PERIOD') { + // Convert the values to integers, sort them, and convert back to strings + List timePeriodData = item['filter_data'] + .map((e) => int.parse(e.toString())) // Convert to int + .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(); + } + } + + print('TABId - $tabId'); print("TABFiltered Data: $filterData"); @@ -1927,6 +1930,10 @@ class _ChartScreen1State extends ConsumerState { }); double myheight = MediaQuery.of(context).size.height; double mywidth = MediaQuery.of(context).size.width; + + int crossAxisCount = cardData.isNotEmpty ? (cardData.length / 2).ceil().clamp(1, 2) : 1; + + final color = Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16)); return PopScope( @@ -1938,45 +1945,6 @@ class _ChartScreen1State extends ConsumerState { child: BaseScaffold( 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( context.translate( 'UAE Numbers', @@ -2035,25 +2003,7 @@ class _ChartScreen1State extends ConsumerState { fontWeight: FontWeight.w400, 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, - // )), - // ], - // ), + ], ), )), @@ -2073,7 +2023,7 @@ class _ChartScreen1State extends ConsumerState { GestureDetector( onTap: () { if (isBookmarked) { - showRemoveBookmarkDialog(); + showRemoveBookmarkDialog(); } else { showAddBookmarkDialog(); } @@ -2194,37 +2144,43 @@ class _ChartScreen1State extends ConsumerState { size: 24, semanticLabel: 'Share', ), + ), ), - ), ], ), SizedBox( width: 10), // Horizontal space between items Row( children: [ - Text( - context.translate( - 'Filter', - 'فلتر', - ), - style: const TextStyle( - fontSize: 16, - color: Colors.white, - ), - ), - SizedBox(width: 10), GestureDetector( onTap: () { showRightSideModal( context, filterData, chartsData); }, - child: Image.asset( + + child: Row( + children: [ + Text( + context.translate( + 'Filter', + 'فلتر', + ), + style: const TextStyle( + fontSize: 16, + color: Colors.white, + ), + ), + + SizedBox(width: 10), + Image.asset( UaeNumbersAssetPath.filterUae, color: Colors.white, // Set color to white width: 21, height: 21, ), + ],), + ) // IconButton( // icon: Icon(Icons.filter_alt_outlined, @@ -2302,32 +2258,26 @@ class _ChartScreen1State extends ConsumerState { // nonChartData Cards Padding( padding: const EdgeInsets.all(3.34), - child: GridView.builder( + + + + child: GridView.builder( key: cardKey, itemCount: cardData.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - // crossAxisCount:2, - 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, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount:crossAxisCount, + // crossAxisCount: cardData.length % 2 == 0 ? 2 : 3, + + crossAxisSpacing: 2, + mainAxisSpacing: 5, childAspectRatio: MediaQuery.of(context) .size .width / (MediaQuery.of(context).size.height / - (cardData.length % 2 == 0 - ? 2 - : 1.3)), + (cardData.length % 2 == 0 ? 2 : 2)), // childAspectRatio: // calculateAspectRatio(cardData.length, cardData), ), @@ -2366,6 +2316,7 @@ class _ChartScreen1State extends ConsumerState { borderRadius: BorderRadius.circular(12), border: Border.all( + color: Color(int.parse( (chartScreenData[ 'border_color'] ?? @@ -2444,15 +2395,17 @@ class _ChartScreen1State extends ConsumerState { height: 20.0, child: FittedBox( child: Text( - '(${response[0]['display_value'] ?? 'NA'})', - // '(${data['firstYear'] ?? - // 'NA'} - ${data['lastYear'] ?? - // 'NA'})', + // '(${response[0]['display_value'] ?? 'NA'})', + RegExp(r'\d').hasMatch(response[0]['display_value'] ?? '') + ? '(${response[0]['display_value'] ?? 'NA'})' + : '${response[0]['display_value'] ?? 'NA'}', style: + const TextStyle( fontSize: 10, - color: Colors - .grey), + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), ), ), ), @@ -2467,60 +2420,35 @@ class _ChartScreen1State extends ConsumerState { child: Row( children: [ Text( - response[0][ - 'value'] ?? - 'NA', + response[0]['value'] ?? 'NA', // '${data['roundedAverage'] ?? // 'NA'}', - style: TextStyle( - fontSize: 20, + style: + TextStyle( + fontSize: 18, fontWeight: - FontWeight - .w900, - color: response[0] - [ - 'calculation'] == - 'different' - ? _getColorFromHex( - response[0] - [ - 'font_color']) - : const Color( - 0xFF90B0D5), + FontWeight.w800, + color: response[0]['calculation'] == 'different' + ? _getColorFromHex(response[0]['font_color']) + : const Color(0xFF90B0D5), // color: Color( // 0xFF90B0D5), ), ), - const SizedBox( - width: - 1), // Space between text and icon - if (response[0][ - 'calculation'] == - 'different') ...[ - 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), + const SizedBox(width: 1), // Space between text and icon + if (response[0]['calculation'] == 'different') ...[ + if (response[0]['font_color'] == '#D83731') + const Icon(Icons.arrow_downward, color: Colors.red, size: 20) + else if (response[0]['font_color'] == '#11AF22') + const Icon(Icons.arrow_upward, color: Colors.green, size: 20), ], ], + ), + ), ), + ), ], ), @@ -2608,12 +2536,16 @@ class _ChartScreen1State extends ConsumerState { ), const SizedBox(height: 1), 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( fontSize: 10, - color: Colors.grey), + color: Colors.grey, + overflow: TextOverflow.ellipsis,), ), const SizedBox(height: 1), Flexible( @@ -2628,18 +2560,13 @@ class _ChartScreen1State extends ConsumerState { // data['lastYearValue']), // apiService.formatAmount( // data['lastYearValue']), - style: TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w900, - color: response[0][ - 'calculation'] == - 'different' - ? _getColorFromHex( - response[0][ - 'font_color']) - : const Color( - 0xFF90B0D5), + color: response[0]['calculation'] == 'different' + ? _getColorFromHex(response[0]['font_color']) + : const Color(0xFF90B0D5), ), ), ), @@ -2666,26 +2593,26 @@ class _ChartScreen1State extends ConsumerState { fontSize: 14, fontWeight: FontWeight.w600, - color: response[1][ - 'calculation'] == - 'different' - ? _getColorFromHex( - response[0][ - 'font_color']) - : const Color( - 0xFFD83731), + + color: response[1]['calculation'] == 'different' + ? _getColorFromHex(response[0]['font_color']) + : const Color(0xFFD83731), + ), ), ), ), Text( - '(${response[1]['display_value'] ?? 'NA'})', - // '(${data['secondLastYear'] ?? 'NA'})', + // '(${response[1]['display_value'] ?? 'NA'})', + RegExp(r'\d').hasMatch(response[1]['display_value'] ?? '') + ? '(${response[1]['display_value'] ?? 'NA'})' + : '${response[1]['display_value'] ?? 'NA'}', style: const TextStyle( fontSize: 9, fontWeight: FontWeight.w500, - color: Colors.grey), + color: Colors.grey, + overflow: TextOverflow.ellipsis,), ), ], ), @@ -2822,4 +2749,4 @@ Color _getColorFromHex(String hexColor) { hexColor = 'FF$hexColor'; // Add alpha if not provided } return Color(int.parse(hexColor, radix: 16)); -} +} \ No newline at end of file diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index 470ebc97..a075d918 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -49,34 +49,22 @@ class ChartWidget extends StatelessWidget { List parsePieChartData( dynamic chartData, double totalValue, - // String totalValue, int? touchedIndex, ) { debugPrint('Chart Data: ${jsonEncode(chartData)}'); + return chartData['response'] .asMap() .entries .map((entry) { int index = entry.key; - print('piePArse'); - 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 double value = 0.0; - var rawValue = data['ObsValue']['Value']; - print('Raw Value: $rawValue (Type: ${rawValue.runtimeType})'); - if (rawValue is String) { value = double.tryParse(rawValue) ?? 0.0; } else if (rawValue is int) { @@ -87,41 +75,27 @@ class ChartWidget extends StatelessWidget { 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 = (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; - return PieChartSectionData( - value: value, - color: Colors.primaries[index % Colors.primaries.length], - title: '${percentage.toStringAsFixed(1)}%', - radius: isTouched ? 60 : 50, + return PieChartSectionData( + value: value, + color: Colors.primaries[index % Colors.primaries.length], + title: '${percentage.toStringAsFixed(1)}%', + radius: isTouched ? 60 : 50, + + // Increase size when touched + titleStyle: TextStyle( + fontSize: isTouched ? 12 : 10, + fontWeight: FontWeight.bold, + color: Colors.black, + // color: Colors.white, + + ), + titlePositionPercentageOffset: 1.3, + ); - // Increase size when touched - titleStyle: TextStyle( - fontSize: isTouched ? 12 : 10, - fontWeight: FontWeight.bold, - color: Colors.black, - // color: Colors.white, - ), - titlePositionPercentageOffset: 1.3, - ); }).toList(); } @@ -135,47 +109,43 @@ class ChartWidget extends StatelessWidget { title.length > 10 ? '${title.substring(0, 10)}…' : title; return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), - ), - SizedBox(width: 8), - TooltipTheme( - data: TooltipThemeData( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 10, + height: 10, decoration: BoxDecoration( - color: Colors.blueGrey[800], // Change background color - borderRadius: - BorderRadius.circular(8), // Optional: rounded corners + color: color, + shape: BoxShape.circle, ), - textStyle: TextStyle(color: Colors.white), // Change text color ), + SizedBox(width: 8), + TooltipTheme( + data: TooltipThemeData( + decoration: BoxDecoration( + color: Colors.blueGrey[800], // Change background color + borderRadius: BorderRadius.circular(8), // Optional: rounded corners + ), + textStyle: TextStyle(color: Colors.white), // Change text color + ), child: Tooltip( message: title, // Full text on hover - child: ConstrainedBox( - // Constrain width to allow wrapping - constraints: BoxConstraints(maxWidth: 100), - child: Text( - title, - style: TextStyle( - fontSize: 12, - ), - softWrap: true, - maxLines: 2, - overflow: - TextOverflow.ellipsis, // Ensures text doesn't overflow - ), + child: ConstrainedBox( // Constrain width to allow wrapping + constraints: BoxConstraints(maxWidth: 100), + child: Text( + title, + style: TextStyle(fontSize: 12,), + softWrap: true, + maxLines: 2, + overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow ), ), - ), - SizedBox(width: 5), - ], - ); + + ),), + SizedBox(width: 5), + ], + ); + }).toList(); } @@ -287,28 +257,12 @@ class ChartWidget extends StatelessWidget { ), ); case 'pie_chart': - double totalValue = chartData['response'].map((entry) { + double totalValue = chartData['response'] + .map((entry) { var value = entry['ObsValue']['Value']; - print( - 'Processing value: $value, type: ${value.runtimeType}'); // Debug each value - 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; + // print('Processing value: $value, type: ${value.runtimeType}'); + return (value is num) ? value.toDouble() : value is String ? double.tryParse(value) ?? 0.0 : 0.0; }).fold(0.0, (prev, element) => prev + element); - // List totalValues = chartData['response'] - // .map((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 touchedIndex = ValueNotifier(null); @@ -324,6 +278,7 @@ class ChartWidget extends StatelessWidget { textAlign: TextAlign.center, ), SizedBox(height: 15), + Text( chartData['chart_sub_heading'] ?? '', style: TextStyle( @@ -333,6 +288,7 @@ class ChartWidget extends StatelessWidget { textAlign: TextAlign.center, ), SizedBox(height: 70), + Expanded( child: ValueListenableBuilder( valueListenable: touchedIndex, @@ -348,26 +304,29 @@ class ChartWidget extends StatelessWidget { touchCallback: (FlTouchEvent event, pieTouchResponse) { if (pieTouchResponse?.touchedSection != null && event is! FlTapUpEvent) { - touchedIndex.value = pieTouchResponse! + touchedIndex.value = pieTouchResponse! .touchedSection!.touchedSectionIndex; } else { touchedIndex.value = null; // Reset when not touching } }, + ), ), ); + }, + ), ), - SizedBox(height: 65), + SizedBox(height:105), Flexible( // child: SingleChildScrollView( // scrollDirection: Axis.horizontal, // child: SingleChildScrollView( - scrollDirection: Axis.vertical, + scrollDirection: Axis.vertical, child: Container( constraints: BoxConstraints(minHeight: 3), // Allow dynamic height @@ -382,7 +341,7 @@ class ChartWidget extends StatelessWidget { ), ), ), - ), + ), // ), ), @@ -422,7 +381,7 @@ class ChartWidget extends StatelessWidget { ), textAlign: TextAlign.center, ), - SizedBox(height: 15), + SizedBox(height: 15), AspectRatio( aspectRatio: 1.5, child: BarChart( @@ -434,11 +393,11 @@ class ChartWidget extends StatelessWidget { fitInsideHorizontally: true, fitInsideVertically: true, // tooltipPadding: const EdgeInsets.all(8), - tooltipPadding: const EdgeInsets.symmetric( - horizontal: 4, vertical: 8), // Optional + tooltipPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8), // Optional tooltipHorizontalAlignment: FLHorizontalAlignment.left, tooltipMargin: 16, + getTooltipItem: (groupData, groupIndex, rodData, rodIndex) { // Get the list of group names dynamically @@ -596,7 +555,7 @@ class ChartWidget extends StatelessWidget { colorIndex % uniqueColorsLine_trend_2.length]; colorIndex++; } - print('LnTrnd1'); + print('LnTrnd1'); // Extract all years from the chart data List years = (chartData['response'] as List) @@ -633,9 +592,10 @@ class ChartWidget extends StatelessWidget { // (entry) => double.parse(entry['ObsKey']['TIME_PERIOD'])) // .toSet(); - Set uniqueXValues = filteredData.map((entry) { - String? timePeriod = - entry['ObsKey']['TIME_PERIOD']; // Nullable String + + Set uniqueXValues = filteredData + .map((entry) { + String? timePeriod = entry['ObsKey']['TIME_PERIOD']; // Nullable String print('TIME_PERIOD- $timePeriod'); if (timePeriod == null) { @@ -657,7 +617,8 @@ class ChartWidget extends StatelessWidget { print('Unknown format: $timePeriod'); return timePeriod; // Keep it as is } - }).toSet(); + }) + .toSet(); print("Unique X Values: $uniqueXValues"); @@ -666,30 +627,18 @@ class ChartWidget extends StatelessWidget { if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) { return double.parse(timePeriod); // Year-only (2019 → 2019.0) } else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) { - return double.parse(timePeriod.replaceAll( - '-', '.')); // Year-Month (2019-11 → 2019.11) + return double.parse(timePeriod.replaceAll('-', '.')); // Year-Month (2019-11 → 2019.11) } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { // Year-MonthAbbr (2019-Nov) Map monthMap = { - 'Jan': 1, - 'Feb': 2, - 'Mar': 3, - 'Apr': 4, - 'May': 5, - 'Jun': 6, - 'Jul': 7, - 'Aug': 8, - 'Sep': 9, - 'Oct': 10, - 'Nov': 11, - 'Dec': 12 + 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, + 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, + 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12 }; List parts = timePeriod.split('-'); - int month = - monthMap[parts[1]] ?? 1; // Default to January if unknown - return double.parse( - '${parts[0]}.$month'); // Convert to format (2019-Nov → 2019.11) + int month = monthMap[parts[1]] ?? 1; // Default to January if unknown + return double.parse('${parts[0]}.$month'); // Convert to format (2019-Nov → 2019.11) } throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); @@ -701,12 +650,15 @@ class ChartWidget extends StatelessWidget { .toSet(); print('Processed X Values: $uniqueXValuesProcessed'); + + print('LnTrnd2.1'); // Generate line bars for the chart List lineBars = lineBarsData(filteredData, groupByValues, groupByKey); + print('LnTrnd3'); return Column(children: [ @@ -730,6 +682,7 @@ class ChartWidget extends StatelessWidget { SizedBox(height: 10), // Chart Expanded( + child: LineChart(LineChartData( lineTouchData: lineTouchData1(), gridData: gridData(), @@ -739,10 +692,12 @@ class ChartWidget extends StatelessWidget { lineBarsData: lineBars, // minX: 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), + // maxX: 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), - ))), + + ), Padding( padding: const EdgeInsets.all(8.0), child: Wrap( @@ -991,17 +946,18 @@ class ChartWidget extends StatelessWidget { // Extract groupBy values and their corresponding y-axis values List xAxisData = []; List yAxisData = []; + List yAxisLabels = []; - var xadditionalgrp = chartData['chart_type_json']['additional_x_group']; + var xadditionalgrp= chartData['chart_type_json']['additional_x_group']; print('xadditionalgrp-$xadditionalgrp'); for (var entry in chartData['response']) { 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 xadditionalgroup = - chartData['chart_type_json']['additional_x_group']; + var xadditionalgroup= chartData['chart_type_json']['additional_x_group']; print('chartData response: ${chartData['response']}'); @@ -1009,22 +965,18 @@ class ChartWidget extends StatelessWidget { print('Xadditionalt-$xTimePeriod'); print('xadditionalgroup-$xadditionalgroup'); print('yValue-$yValue'); + print('unitMsr-$unitMsr'); + if (xadditionalgrp == 'TIME_PERIOD') { chartData['response'].sort((a, b) { // Convert TIME_PERIOD to int for proper sorting - int timeA = - int.tryParse(a['ObsKey']['TIME_PERIOD'].toString()) ?? 0; - int timeB = - int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0; + int timeA = int.tryParse(a['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 - int quarterA = int.tryParse( - a['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? - 0; - int quarterB = int.tryParse( - b['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? - 0; + int quarterA = int.tryParse(a['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? 0; + int quarterB = int.tryParse(b['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ?? 0; // First, sort by TIME_PERIOD. If equal, sort by QUARTER if (timeA != timeB) { @@ -1047,8 +999,12 @@ class ChartWidget extends StatelessWidget { } xAxisData.add(xLabel); + yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); + yAxisLabels.add(unitMsr ?? ''); + } + } return Column(children: [ Text( @@ -1077,7 +1033,9 @@ class ChartWidget extends StatelessWidget { maxY: yAxisData.isNotEmpty ? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2 : 10, - // barTouchData: BarTouchData(enabled: true), + + + // barTouchData: BarTouchData(enabled: true), barTouchData: BarTouchData( enabled: true, handleBuiltInTouches: true, @@ -1087,8 +1045,13 @@ class ChartWidget extends StatelessWidget { // tooltipPadding: const EdgeInsets.all(8), // tooltipMargin: 16, getTooltipItem: (group, groupIndex, rod, rodIndex) { + + String unitMsrLabel = yAxisLabels.isNotEmpty && groupIndex < yAxisLabels.length + ? yAxisLabels[groupIndex] + : ''; + return BarTooltipItem( - rod.toY.toStringAsFixed(1), + '${rod.toY.toStringAsFixed(1)}\n$unitMsrLabel', const TextStyle(color: Colors.white), ); }, @@ -1122,8 +1085,7 @@ class ChartWidget extends StatelessWidget { : title; return Padding( - padding: - const EdgeInsets.only(top: 8.0, left: 55.0), + padding: const EdgeInsets.only(top: 8.0,left: 55.0), child: SizedBox( width: 60, // Limit width to force wrapping child: Transform.rotate( @@ -1131,43 +1093,36 @@ class ChartWidget extends StatelessWidget { angle: -1.5, child: TooltipTheme( - data: TooltipThemeData( - decoration: BoxDecoration( - color: Colors.blueGrey[ - 800], // Change background color - borderRadius: BorderRadius.circular( - 8), // Optional: rounded corners + data: TooltipThemeData( + decoration: BoxDecoration( + color: Colors.blueGrey[800], // Change background color + borderRadius: BorderRadius.circular(8), // Optional: rounded corners + ), + textStyle: TextStyle(color: Colors.white), // Change text color ), - textStyle: TextStyle( - color: Colors - .white), // Change text color - ), + child: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( - color: Colors.blueGrey[ - 800], // Change background color - borderRadius: BorderRadius.circular( - 8), // Optional: rounded corners - ), - textStyle: TextStyle( - color: Colors - .white), // Change text color - ), - child: Tooltip( - message: title, - child: Text( - // title, - displayTitle, - softWrap: true, - style: TextStyle( - fontSize: 10, - ), - overflow: TextOverflow.ellipsis, + color: Colors.blueGrey[800], // Change background color + borderRadius: BorderRadius.circular(8), // Optional: rounded corners ), + textStyle: TextStyle(color: Colors.white), // Change text color ), + child: Tooltip( + message: title, + + child: Text( + // title, + displayTitle, + softWrap: true, + style: TextStyle(fontSize: 10,), + overflow: TextOverflow.ellipsis, + ),), ), + ), + ))); } return Container(); @@ -1237,104 +1192,102 @@ class ChartWidget extends StatelessWidget { SizedBox(height: 10), // Chart Expanded( - child: BarChart( - BarChartData( - alignment: BarChartAlignment.spaceAround, - maxY: yAxisData.isNotEmpty - ? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2 - : 10, - rotationQuarterTurns: rotationTurns, - barTouchData: BarTouchData( - enabled: true, - handleBuiltInTouches: true, - touchTooltipData: BarTouchTooltipData( - fitInsideHorizontally: true, - fitInsideVertically: true, - tooltipPadding: const EdgeInsets.all(8), - tooltipMargin: 16, - getTooltipItem: (group, groupIndex, rod, rodIndex) { - return BarTooltipItem( - '${rod.toY.toStringAsFixed(1)}', - const TextStyle(color: Colors.white), + child: BarChart( + BarChartData( + alignment: BarChartAlignment.spaceAround, + maxY: yAxisData.isNotEmpty + ? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2 + : 10, + rotationQuarterTurns: rotationTurns, + barTouchData: BarTouchData( + enabled: true, + handleBuiltInTouches: true, + touchTooltipData: BarTouchTooltipData( + fitInsideHorizontally: true, + fitInsideVertically: true, + tooltipPadding: const EdgeInsets.all(8), + tooltipMargin: 16, + getTooltipItem: (group, groupIndex, rod, rodIndex) { + return BarTooltipItem( + '${rod.toY.toStringAsFixed(1)}', + const TextStyle(color: Colors.white), + ); + }, + ), + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + interval: (yAxisData.isNotEmpty + ? yAxisData.reduce((a, b) => a > b ? a : b) / 5 + : 1), + getTitlesWidget: (value, meta) { + return Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Text('${value.toInt()}'), ); }, + reservedSize: 60, ), ), - titlesData: FlTitlesData( - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: false, - interval: (yAxisData.isNotEmpty - ? yAxisData.reduce((a, b) => a > b ? a : b) / 5 - : 1), - getTitlesWidget: (value, meta) { + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + if (value.toInt() < xAxisData.length) { return Padding( - padding: const EdgeInsets.only(right: 8.0), - child: Text('${value.toInt()}'), - ); - }, - reservedSize: 60, - ), - ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: (value, meta) { - if (value.toInt() < xAxisData.length) { - return Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Transform.rotate( - angle: -1.58, - // angle: -45 * - // (3.1415927 / 180), // Rotating by -45 degrees - alignment: Alignment.center, - child: Center( - child: SizedBox( - width: 100, - child: Text( - xAxisData[value.toInt()], - style: const TextStyle(fontSize: 12), - softWrap: true, - maxLines: 3, - ), + padding: const EdgeInsets.only(top: 8.0), + child: Transform.rotate( + angle: -1.58, + // angle: -45 * + // (3.1415927 / 180), // Rotating by -45 degrees + alignment: Alignment.center, + child: Center( + child: SizedBox( + width: 100, + child: Text( + xAxisData[value.toInt()], + style: const TextStyle(fontSize: 12), + softWrap: true, + maxLines: 3, ), ), ), - ); - } - return Container(); - }, - reservedSize: 85, - ), - ), - topTitles: AxisTitles( - sideTitles: - SideTitles(showTitles: false), // Hide top titles - ), - rightTitles: AxisTitles( - sideTitles: - SideTitles(showTitles: false), // Hide right titles + ), + ); + } + return Container(); + }, + reservedSize: 85, ), ), - gridData: FlGridData(show: false), - borderData: FlBorderData(show: false), - barGroups: List.generate( - xAxisData.length, - (index) => BarChartGroupData( - x: index, - barRods: [ - BarChartRodData( - toY: yAxisData[index], - color: Colors.blueAccent, - borderRadius: BorderRadius.circular(4), - width: 20, - ), - ], - ), + topTitles: AxisTitles( + sideTitles: SideTitles(showTitles: false), // Hide top titles + ), + rightTitles: AxisTitles( + sideTitles: + SideTitles(showTitles: false), // Hide right titles + ), + ), + gridData: FlGridData(show: false), + borderData: FlBorderData(show: false), + barGroups: List.generate( + xAxisData.length, + (index) => BarChartGroupData( + x: index, + barRods: [ + BarChartRodData( + toY: yAxisData[index], + color: Colors.blueAccent, + borderRadius: BorderRadius.circular(4), + width: 20, + ), + ], ), ), ), - ), + ),), ]); case 'fl_multi_bar': double _calculateChartWidth(dynamic chartData) { @@ -1346,10 +1299,14 @@ class ChartWidget extends StatelessWidget { // Group crops by CROP_TYPE Map> groupedCrops = {}; + int touchedGroupIndex = -1; // Iterate over the chartData to group crops by CROP_TYPE + + for (var item in chartData['response']) { + print("MultiBArRaw item: $item"); String crop = item['ObsKey'][cropKey]; @@ -1357,8 +1314,7 @@ class ChartWidget extends StatelessWidget { // Use a Set to avoid duplicates if (groupedCrops.containsKey(cropType)) { - groupedCrops[cropType] = - (groupedCrops[cropType]! + [crop]).toSet().toList(); + groupedCrops[cropType] = (groupedCrops[cropType]! + [crop]).toSet().toList(); } else { groupedCrops[cropType] = [crop]; } @@ -1380,6 +1336,7 @@ class ChartWidget extends StatelessWidget { // // print('groupedCropsflmutli- $groupedCrops'); + return Center( child: Column(children: [ Text( @@ -1410,8 +1367,8 @@ class ChartWidget extends StatelessWidget { child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, - maxY: _calculateMaxY( - chartData), // Dynamically calculate max Y + maxY: + _calculateMaxY(chartData), // Dynamically calculate max Y barGroups: _buildHorizontalRotateBarGroups( chartData, groupByValues), // Build bar groups titlesData: FlTitlesData( @@ -1434,31 +1391,27 @@ class ChartWidget extends StatelessWidget { return Padding( padding: const EdgeInsets.only(top: 8.0), child: SizedBox( - width: - 60, // Limit width to force wrapping + width: 60, // Limit width to force wrapping child: Transform.rotate( angle: -0.5, - child: TooltipTheme( - data: TooltipThemeData( - decoration: BoxDecoration( - color: Colors.blueGrey[ - 800], // Change background color - borderRadius: BorderRadius.circular( - 8), // Optional: rounded corners + child: TooltipTheme( + data: TooltipThemeData( + decoration: BoxDecoration( + color: Colors.blueGrey[800], // Change background color + borderRadius: BorderRadius.circular(8), // Optional: rounded corners + ), + textStyle: TextStyle(color: Colors.white), // Change text color ), - textStyle: TextStyle( - color: Colors - .white), // Change text color + child: Tooltip( + message: title, + child: Text( + displayTitle, + softWrap: true, + // style: TextStyle(backgroundColor: Colors.blueGrey[800]), + overflow: TextOverflow.ellipsis, + )), + ), - child: Tooltip( - message: title, - child: Text( - displayTitle, - softWrap: true, - // style: TextStyle(backgroundColor: Colors.blueGrey[800]), - overflow: TextOverflow.ellipsis, - )), - ), ))); // return Transform.rotate( // angle: @@ -1481,8 +1434,7 @@ class ChartWidget extends StatelessWidget { borderData: FlBorderData(show: false), barTouchData: BarTouchData( touchTooltipData: BarTouchTooltipData( - tooltipHorizontalAlignment: - FLHorizontalAlignment.center, + tooltipHorizontalAlignment: FLHorizontalAlignment.center, tooltipRoundedRadius: 8, fitInsideHorizontally: true, // Ensure it fits within the screen @@ -1500,8 +1452,7 @@ class ChartWidget extends StatelessWidget { groupByValues.elementAt(groupIndex); // Fetch the crop for the current group from groupedCrops - String cropType = - groupByValues.elementAt(groupIndex); + String cropType = groupByValues.elementAt(groupIndex); print('GrpcropType: $cropType'); // String crop = groupedCrops[cropType]![rodIndex]; @@ -1514,9 +1465,7 @@ class ChartWidget extends StatelessWidget { print( 'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex'); // crop = cropType; // Fallback to cropType - crop = (crops != null && crops.isNotEmpty) - ? crops.first - : cropType; + crop = (crops != null && crops.isNotEmpty) ? crops.first : cropType; } // print('groupedCrops1: $groupedCrops - $rodIndex'); @@ -1563,8 +1512,7 @@ class ChartWidget extends StatelessWidget { response != null && response.spot != null) { // setState(() { - touchedGroupIndex = - response.spot!.touchedBarGroupIndex; + touchedGroupIndex = response.spot!.touchedBarGroupIndex; // }); } else { // setState(() { @@ -1607,10 +1555,10 @@ class ChartWidget extends StatelessWidget { int numberOfBars = groupedCrops.length; // Number of grouped sets (bar groups) - double barHeight = 40.0; // Height per individual bar - double barSpacing = 30.0; // Space between bar sets + double barHeight = 10.0; // Height per individual bar + double barSpacing = 1.0; // Space between bar sets 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 double chartHeight = @@ -1629,6 +1577,7 @@ class ChartWidget extends StatelessWidget { SizedBox(height: 5), Text( chartData['chart_sub_heading'] ?? '', + style: TextStyle( fontSize: 13, fontWeight: FontWeight.w300, @@ -1640,22 +1589,24 @@ class ChartWidget extends StatelessWidget { Expanded( child: SingleChildScrollView( scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, + // child: SingleChildScrollView( + // scrollDirection: Axis.horizontal, + child: SizedBox( - width: 1000, + // width: 500, + // width: 1000, height: chartHeight, - child: BarChart( + child: Stack( + children: [ + BarChart( BarChartData( maxY: 400000, rotationQuarterTurns: rotationTurns, barTouchData: BarTouchData( touchTooltipData: BarTouchTooltipData( - tooltipHorizontalAlignment: - FLHorizontalAlignment.center, + tooltipHorizontalAlignment: FLHorizontalAlignment.center, tooltipRoundedRadius: 8, - fitInsideHorizontally: - true, // Ensure it fits within the screen + fitInsideHorizontally: true, // Ensure it fits within the screen fitInsideVertically: true, tooltipPadding: EdgeInsets.all(8), tooltipMargin: 16, @@ -1728,21 +1679,24 @@ class ChartWidget extends StatelessWidget { titlesData: FlTitlesData( leftTitles: AxisTitles( sideTitles: SideTitles( - showTitles: false, - reservedSize: 20, + // showTitles: false, + reservedSize: 40, interval: 100000, getTitlesWidget: (value, meta) { - return Text( + return SizedBox( + width: 50, + child: Text( value.toInt().toString(), - style: const TextStyle(fontSize: 12), - ); + textAlign: TextAlign.justify, + style: const TextStyle(fontSize: 12,), + ),); }, ), ), bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, - reservedSize: 80, // Added space for rotated titles + reservedSize: 150, // Added space for rotated titles getTitlesWidget: (value, meta) { if (value < groupByValues.length) { String title = @@ -1752,9 +1706,10 @@ class ChartWidget extends StatelessWidget { -1.58, // Rotation in radians (~ -30 degrees) child: Center( child: SizedBox( - width: 80, + width: 120, child: Text( title, + textAlign: TextAlign.end, style: const TextStyle(fontSize: 12), softWrap: true, maxLines: 2, @@ -1802,191 +1757,13 @@ class ChartWidget extends StatelessWidget { 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: @@ -2083,6 +1860,7 @@ class ChartWidget extends StatelessWidget { return lineBars; } + /// Function to parse TIME_PERIOD into a EXACT value double parseTimePeriod(String timePeriod) { // Match formats @@ -2091,23 +1869,13 @@ class ChartWidget extends StatelessWidget { return double.parse(timePeriod); // Year as a double (2020 → 2020.0) } else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) { // Format: Year-Month (e.g., "2020-10") - return double.parse( - timePeriod.replaceAll('-', '.')); // Convert "2020-10" → 2020.10 + return double.parse(timePeriod.replaceAll('-', '.')); // Convert "2020-10" → 2020.10 } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { // Format: Year-MonthAbbr (e.g., "2020-Oct") Map monthMap = { - 'Jan': 1, - 'Feb': 2, - 'Mar': 3, - 'Apr': 4, - 'May': 5, - 'Jun': 6, - 'Jul': 7, - 'Aug': 8, - 'Sep': 9, - 'Oct': 10, - 'Nov': 11, - 'Dec': 12 + 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, + 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, + 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12 }; List parts = timePeriod.split('-'); @@ -2119,6 +1887,7 @@ class ChartWidget extends StatelessWidget { throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); } + List lineBarsData(List filteredData, Set groupByValues, String groupByKey) { List lineBars = []; @@ -2183,6 +1952,9 @@ class ChartWidget extends StatelessWidget { print('spots - $spots'); + + + // List spots = filteredData // .where((entry) => entry['ObsKey'][groupByKey] == group) // .map((entry) { @@ -2198,6 +1970,8 @@ class ChartWidget extends StatelessWidget { // return FlSpot(xValue, yValue); // }).toList(); + + print('lineGrp2'); // Add a line for this group lineBars.add( @@ -2207,7 +1981,9 @@ class ChartWidget extends StatelessWidget { color: groupColorMap[group], barWidth: 3, isStrokeCapRound: true, + dotData: FlDotData(show: true), belowBarData: BarAreaData(show: false), + ), ); } @@ -2242,11 +2018,11 @@ class ChartWidget extends StatelessWidget { } FlTitlesData titlesData1(Set xValues) { + print('tileDATa1xvalue - $xValues'); double findClosest(double value, Set values) { - return values - .reduce((a, b) => (value - a).abs() < (value - b).abs() ? a : b); + return values.reduce((a, b) => (value - a).abs() < (value - b).abs() ? a : b); } return FlTitlesData( @@ -2259,16 +2035,18 @@ class ChartWidget extends StatelessWidget { String formattedValue; if (value % 10 == 0) { - // 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) { - formattedValue = - '${(value / 1000000000000).toStringAsFixed(0)}T'; - } else if (value >= 1000000000) { + formattedValue = '${(value / 1000000000000).toStringAsFixed(0)}T'; + } + else if (value >= 1000000000) { formattedValue = '${(value / 1000000000).toStringAsFixed(0)}B'; - } else if (value >= 1000000) { + } + else if (value >= 1000000) { formattedValue = '${(value / 1000000).toStringAsFixed(0)}M'; - } else if (value >= 1000) { + } + else if (value >= 1000) { formattedValue = '${(value / 1000).toStringAsFixed(0)}k'; } else { formattedValue = value.toStringAsFixed( @@ -2300,11 +2078,14 @@ class ChartWidget extends StatelessWidget { interval: null, // interval: 10, // Ensure each year is shown only once getTitlesWidget: (value, meta) { + print('BtmTiles :-$value'); print('BtmTilesmeta :-$meta'); // if (xValues.contains(value)) double closestValue = findClosest(value, xValues); - if ((closestValue - value).abs() < 0.15) { + if ((closestValue - value).abs() < 0.15) + { + print("Bottomtiles"); print(value); return Padding( @@ -2430,8 +2211,7 @@ class ChartWidget extends StatelessWidget { width: 20, // width: barWidth, borderRadius: BorderRadius.zero, - color: Colors - .transparent, // This will act as a container for stacked items + color: Colors.black// This will act as a container for stacked items ), ], ); @@ -2596,6 +2376,7 @@ class ChartWidget extends StatelessWidget { toY: value, // Use the parsed value color: barColor, // Dynamic color width: 20, + // backDrawRodData: BackgroundBarChartRodData( // show: true, // toY: 400000, @@ -2626,6 +2407,7 @@ class ChartWidget extends StatelessWidget { } } + double calculateBarWidth(BuildContext context, int totalBars) { double width = MediaQuery.of(context).size.width; // Chart width double padding = 16.0; // Space between bars @@ -2658,4 +2440,4 @@ class ChartData { final DateTime? xDateTime; ChartData({this.x, required this.y, this.xDateTime}); -} +} \ No newline at end of file