diff --git a/android/app/build.gradle b/android/app/build.gradle index c8d2d5d2..21ef3342 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) { def flutterVersionCode = localProperties.getProperty("flutter.versionCode") if (flutterVersionCode == null) { - flutterVersionCode = "21" + flutterVersionCode = "24" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.20" + flutterVersionName = "1.0.23" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index c684b827..e8a10522 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -80,7 +80,7 @@ class _ChartScreen1State extends ConsumerState { print(' bgColor $bgColor'); // fetchChartData(widget.dataSets); checkIfBookmarked(); - locale = ref.read(localeProvider)?? const Locale('en'); + locale = ref.read(localeProvider) ?? const Locale('en'); fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) { if (_tabsData.isNotEmpty) { // Call onTabSelected for the first tab @@ -310,6 +310,7 @@ class _ChartScreen1State extends ConsumerState { ), ); } + //when the popup need for bookmark // void showAddBookmarkDialog() { // double myheight = MediaQuery.of(context).size.height; @@ -398,15 +399,15 @@ class _ChartScreen1State extends ConsumerState { // } void showAddBookmarkDialog() { addBookmark(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'The bookmark is added successfully', - ), - backgroundColor: Colors.green, - duration: Duration(seconds: 2), - ), - ); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text( + // 'The bookmark is added successfully', + // ), + // backgroundColor: Colors.green, + // duration: Duration(seconds: 2), + // ), + // ); } void handleSkip() { @@ -539,9 +540,14 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null, + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : null, border: Border.all( - color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0), + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : Colors.white, + width: 2.0), ), child: IconButton( iconSize: 20, @@ -551,8 +557,13 @@ class _ChartScreen1State extends ConsumerState { if (locale.languageCode == 'ar') { tutorialCoachMark.next(); } else { - ref.read(chartsTourProvider.notifier).state = true; - ref.read(previousHomeTourProvider.notifier).state = false; + ref + .read(chartsTourProvider.notifier) + .state = true; + ref + .read(previousHomeTourProvider + .notifier) + .state = false; tutorialCoachMark.finish(); } }, @@ -562,9 +573,14 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC), + color: locale.languageCode == 'ar' + ? null + : Color(0xFF7DAFBC), border: Border.all( - color:locale.languageCode=='ar' ? Colors.white: Color(0xFF7DAFBC), width: 1), + color: locale.languageCode == 'ar' + ? Colors.white + : Color(0xFF7DAFBC), + width: 1), ), child: IconButton( iconSize: 20, @@ -572,8 +588,13 @@ class _ChartScreen1State extends ConsumerState { color: Colors.white), onPressed: () { if (locale.languageCode == 'ar') { - ref.read(chartsTourProvider.notifier).state = true; - ref.read(previousHomeTourProvider.notifier).state = false; + ref + .read(chartsTourProvider.notifier) + .state = true; + ref + .read(previousHomeTourProvider + .notifier) + .state = false; tutorialCoachMark.finish(); } else { tutorialCoachMark.next(); @@ -627,7 +648,7 @@ class _ChartScreen1State extends ConsumerState { text: AppLocalizations.of(context)!.bookMark, alignment: ContentAlign.bottom, gap: 53, - space: screenWidth*0.22, + space: screenWidth * 0.22, ), TargetContent( align: ContentAlign.bottom, @@ -682,18 +703,29 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null, + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : null, border: Border.all( - color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0), + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : Colors.white, + width: 2.0), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_back, - color: Colors.white,), + icon: const Icon( + Icons.arrow_back, + color: Colors.white, + ), onPressed: () { if (locale.languageCode == 'ar') { - ref.read(chartsTourProvider.notifier).state = true; - ref.read(scaffoldTourProvider.notifier).state = false; + ref + .read(chartsTourProvider.notifier) + .state = true; + ref + .read(scaffoldTourProvider.notifier) + .state = false; tutorialCoachMark.finish(); } else { tutorialCoachMark.previous(); @@ -705,23 +737,33 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC), + color: locale.languageCode == 'ar' + ? null + : Color(0xFF7DAFBC), border: Border.all( - color:locale.languageCode=='ar' ? Colors.white: Color(0xFF7DAFBC), width: 1), + color: locale.languageCode == 'ar' + ? Colors.white + : Color(0xFF7DAFBC), + width: 1), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_forward, - color: Colors.white,), + icon: const Icon( + Icons.arrow_forward, + color: Colors.white, + ), onPressed: () { if (locale.languageCode == 'ar') { tutorialCoachMark.previous(); } else { - ref.read(chartsTourProvider.notifier).state = true; - ref.read(scaffoldTourProvider.notifier).state = false; + ref + .read(chartsTourProvider.notifier) + .state = true; + ref + .read(scaffoldTourProvider.notifier) + .state = false; tutorialCoachMark.finish(); } - }, ), ), @@ -741,7 +783,7 @@ class _ChartScreen1State extends ConsumerState { align: ContentAlign.right, child: Container( width: screenWidth / 4, - height: screenHeight*0.2, + height: screenHeight * 0.2, child: Stack( children: [ Image.asset( @@ -770,7 +812,7 @@ class _ChartScreen1State extends ConsumerState { contents: [ createTargetContent( text: AppLocalizations.of(context)!.bookMark, - space:screenWidth*0.22, + space: screenWidth * 0.22, alignment: ContentAlign.bottom, gap: 53, ), @@ -827,18 +869,30 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null, + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : null, border: Border.all( - color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0,), + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : Colors.white, + width: 2.0, + ), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_back, - color: Colors.white,), + icon: const Icon( + Icons.arrow_back, + color: Colors.white, + ), onPressed: () { if (locale.languageCode == 'ar') { - ref.read(chartsTourProvider.notifier).state = true; - ref.read(scaffoldTourProvider.notifier).state = false; + ref + .read(chartsTourProvider.notifier) + .state = true; + ref + .read(scaffoldTourProvider.notifier) + .state = false; tutorialCoachMark.finish(); } else { tutorialCoachMark.next(); @@ -850,9 +904,15 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC), + color: locale.languageCode == 'ar' + ? null + : Color(0xFF7DAFBC), border: Border.all( - color:locale.languageCode=='ar' ? Colors.white : Color(0xFF7DAFBC), width: 2.0,), + color: locale.languageCode == 'ar' + ? Colors.white + : Color(0xFF7DAFBC), + width: 2.0, + ), ), child: IconButton( iconSize: 20, @@ -862,8 +922,12 @@ class _ChartScreen1State extends ConsumerState { if (locale.languageCode == 'ar') { tutorialCoachMark.next(); } else { - ref.read(chartsTourProvider.notifier).state = true; - ref.read(scaffoldTourProvider.notifier).state = false; + ref + .read(chartsTourProvider.notifier) + .state = true; + ref + .read(scaffoldTourProvider.notifier) + .state = false; tutorialCoachMark.finish(); } }, @@ -885,7 +949,7 @@ class _ChartScreen1State extends ConsumerState { align: ContentAlign.right, child: SizedBox( width: screenWidth / 4, - height:screenHeight*0.2, + height: screenHeight * 0.2, child: Stack( children: [ Image.asset( @@ -964,23 +1028,36 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null, + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : null, border: Border.all( - color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0,), + color: locale.languageCode == 'ar' + ? Color(0xFF7DAFBC) + : Colors.white, + width: 2.0, + ), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_back, - color: Colors.white,), + icon: const Icon( + Icons.arrow_back, + color: Colors.white, + ), onPressed: () { if (locale.languageCode == 'ar') { tutorialCoachMark.previous(); } else { - ref.read(previousChartsTourProvider.notifier).state = true; - ref.read(previousHomeTourProvider.notifier).state = false; + ref + .read(previousChartsTourProvider + .notifier) + .state = true; + ref + .read(previousHomeTourProvider + .notifier) + .state = false; tutorialCoachMark.finish(); } - }, ), ), @@ -988,18 +1065,31 @@ class _ChartScreen1State extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC), + color: locale.languageCode == 'ar' + ? null + : Color(0xFF7DAFBC), border: Border.all( - color:locale.languageCode=='ar' ? Colors.white: Color(0xFF7DAFBC), width: 1), + color: locale.languageCode == 'ar' + ? Colors.white + : Color(0xFF7DAFBC), + width: 1), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_forward, - color: Colors.white,), + icon: const Icon( + Icons.arrow_forward, + color: Colors.white, + ), onPressed: () { if (locale.languageCode == 'ar') { - ref.read(previousChartsTourProvider.notifier).state = true; - ref.read(previousHomeTourProvider.notifier).state = false; + ref + .read(previousChartsTourProvider + .notifier) + .state = true; + ref + .read(previousHomeTourProvider + .notifier) + .state = false; tutorialCoachMark.finish(); } else { tutorialCoachMark.previous(); @@ -1217,6 +1307,7 @@ class _ChartScreen1State extends ConsumerState { for (var chart in data) { final groupBy = chart['group_by']; List response = chart['response'] ?? []; + final chartHeading = chart['chart_heading']; // Filter the response based on selected filters var chartFilteredData = response.where((responseItem) { @@ -1243,6 +1334,26 @@ class _ChartScreen1State extends ConsumerState { }); }).toList(); + print('chartFilteredData- $chartFilteredData'); + + // 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"); + } + + // Add the complete chart data to the filteredData list + filteredData.add({ + ...chart, + 'response': response, // Return full unfiltered response + }); + + continue; + } + // If any data matches the filter, add the whole chart data object // Add filtered chart only once if (chartFilteredData.isNotEmpty && @@ -1996,6 +2107,7 @@ class _ChartScreen1State extends ConsumerState { color: isBookmarked ? Colors.black : Colors.white, + size: 23, ), ], ), @@ -2015,7 +2127,7 @@ class _ChartScreen1State extends ConsumerState { color: Colors.white, ), ), - SizedBox(width: 5), + SizedBox(width: 6), Stack( children: [ // Image.asset( @@ -2031,7 +2143,6 @@ class _ChartScreen1State extends ConsumerState { // height: 24, // ), - SvgPicture.asset( UaeNumbersAssetPath.share, semanticsLabel: 'share', @@ -2056,6 +2167,8 @@ class _ChartScreen1State extends ConsumerState { color: Colors.white, ), ), + + SizedBox(width: 10), GestureDetector( onTap: () { showRightSideModal( @@ -2233,10 +2346,12 @@ class _ChartScreen1State extends ConsumerState { right: 16.0, bottom: 1.0, top: 1.0), - decoration: BoxDecoration( - color: Colors.white, // Move color inside BoxDecoration - borderRadius: BorderRadius.circular(12), // Ensure border radius is applied - ), + decoration: BoxDecoration( + color: Colors + .white, // Move color inside BoxDecoration + borderRadius: BorderRadius.circular( + 12), // Ensure border radius is applied + ), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: @@ -2280,20 +2395,22 @@ class _ChartScreen1State extends ConsumerState { const SizedBox(height: 5), Flexible( fit: FlexFit.loose, - child: SizedBox( - height: 20.0, - child: FittedBox( - child: Text( - '(${response[0]['display_value'] ?? 'NA'})', - // '(${data['firstYear'] ?? - // 'NA'} - ${data['lastYear'] ?? - // 'NA'})', - style: const TextStyle( - fontSize: 10, - color: Colors.grey), + child: SizedBox( + height: 20.0, + child: FittedBox( + child: Text( + '(${response[0]['display_value'] ?? 'NA'})', + // '(${data['firstYear'] ?? + // 'NA'} - ${data['lastYear'] ?? + // 'NA'})', + style: + const TextStyle( + fontSize: 10, + color: Colors + .grey), + ), ), ), - ), ), const SizedBox(height: 1), Flexible( @@ -2302,20 +2419,60 @@ class _ChartScreen1State extends ConsumerState { height: 50.0, child: FittedBox( fit: BoxFit.contain, - child: Text( - response[0] - ['value'] ?? - 'NA', - // '${data['roundedAverage'] ?? - // 'NA'}', - style: - const TextStyle( - fontSize: 20, - fontWeight: - FontWeight.w900, - color: Color( - 0xFF90B0D5), - ), + child: Row( + children: [ + Text( + response[0][ + 'value'] ?? + 'NA', + // '${data['roundedAverage'] ?? + // 'NA'}', + style: TextStyle( + fontSize: 20, + fontWeight: + FontWeight + .w900, + 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), + ], + ], ), ), ), @@ -2352,8 +2509,10 @@ class _ChartScreen1State extends ConsumerState { height: cardHeight, padding: const EdgeInsets.all(10.0), decoration: BoxDecoration( - color: Colors.white, // Move color inside BoxDecoration - borderRadius: BorderRadius.circular(12), // Ensure border radius is applied + color: Colors + .white, // Move color inside BoxDecoration + borderRadius: BorderRadius.circular( + 12), // Ensure border radius is applied ), child: Column( mainAxisSize: MainAxisSize @@ -2424,12 +2583,18 @@ class _ChartScreen1State extends ConsumerState { // data['lastYearValue']), // apiService.formatAmount( // data['lastYearValue']), - style: const TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w900, - color: - Color(0xFF90B0D5), + color: response[0][ + 'calculation'] == + 'different' + ? _getColorFromHex( + response[0][ + 'font_color']) + : const Color( + 0xFF90B0D5), ), ), ), @@ -2452,12 +2617,18 @@ class _ChartScreen1State extends ConsumerState { 'NA', // apiService.formatAmount( // data['secondLastYearValue']), - style: const TextStyle( + style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: - Color(0xFFD83731), + color: response[1][ + 'calculation'] == + 'different' + ? _getColorFromHex( + response[0][ + 'font_color']) + : const Color( + 0xFFD83731), ), ), ), @@ -2487,47 +2658,48 @@ class _ChartScreen1State extends ConsumerState { physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { return Card( - margin: const EdgeInsets.all(10), - child: Container( + margin: const EdgeInsets.all(10), + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Color( + int.parse( + (chartScreenData[ + 'border_color'] ?? + '#898C81') + .replaceFirst('#', '0xff'), + ), + ), // Border color + width: 1, // Border width + ), + color: Colors.white, + borderRadius: BorderRadius.circular( + 8), // Optional: Rounded corners + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + // ConstrainedBox + Container( + // constraints: const BoxConstraints( + // minHeight: + // 200, // Minimum height + // maxHeight: + // 400, // Maximum height + // ), + height: 350, - - decoration: BoxDecoration( - border: Border.all( - color: Color(int.parse((chartScreenData[ - 'border_color'] ?? '#898C81') - .replaceFirst('#', '0xff'),),), // Border color - width: 1, // Border width - ), - color: Colors.white, - borderRadius: BorderRadius.circular(8), // Optional: Rounded corners - ), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - - - // ConstrainedBox - Container - ( - // constraints: const BoxConstraints( - // minHeight: - // 200, // Minimum height - // maxHeight: - // 400, // Maximum height - // ), - height: 320, - - // child: buildChart(chartsData[index]), - child: ChartWidget( - chartData: - chartsData[index])) - ], - ), - ), - ); + // child: buildChart(chartsData[index]), + child: ChartWidget( + chartData: + chartsData[index])) + ], + ), + ), + )); }, ), ], @@ -2574,7 +2746,7 @@ class _ChartScreen1State extends ConsumerState { onTap: () { setState(() { _activeTabIndex = _tabsData.indexOf(tab); - }); + }); _scrollToIndex(_activeTabIndex); onTabSelected(tab['id']!); }, @@ -2596,4 +2768,13 @@ class _ChartScreen1State extends ConsumerState { ), ); } -} \ No newline at end of file +} + +// Function to convert hex color string to Color +Color _getColorFromHex(String hexColor) { + hexColor = hexColor.replaceFirst('#', ''); + if (hexColor.length == 6) { + hexColor = 'FF$hexColor'; // Add alpha if not provided + } + return Color(int.parse(hexColor, radix: 16)); +} diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index 7fe541dc..470ebc97 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; @@ -48,8 +49,11 @@ class ChartWidget extends StatelessWidget { List parsePieChartData( dynamic chartData, double totalValue, + // String totalValue, int? touchedIndex, ) { + debugPrint('Chart Data: ${jsonEncode(chartData)}'); + return chartData['response'] .asMap() .entries @@ -69,27 +73,54 @@ class ChartWidget extends StatelessWidget { // Handle different types: int, double, and String double value = 0.0; - 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 + 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) { + value = rawValue.toDouble(); + } else if (rawValue is double) { + value = rawValue; + } else { + print('Unexpected Type for ObsValue[Value]: ${rawValue.runtimeType}'); } - print('piePArse1 - $value'); - double percentage = (value / totalValue) * 100; + // 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, // Increase size when touched + radius: isTouched ? 60 : 50, + + // Increase size when touched titleStyle: TextStyle( fontSize: isTouched ? 12 : 10, fontWeight: FontWeight.bold, - color: Colors.white, + color: Colors.black, + // color: Colors.white, ), + titlePositionPercentageOffset: 1.3, ); }).toList(); } @@ -116,21 +147,33 @@ class ChartWidget extends StatelessWidget { ), 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: Text( - shortTitle, - style: TextStyle(fontSize: 12), - overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow + 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 + ), + ), + ), + ), + SizedBox(width: 5), ], ); }).toList(); @@ -152,6 +195,8 @@ class ChartWidget extends StatelessWidget { return Center(child: Text('No chart data available')); } + print(chartData['chart_type_json']['TIME_PERIOD']); + String groupByKey = chartData['group_by'] ?? ''; print('groupByKey $groupByKey'); Set groupByValues = extractGroupByValues(chartData, groupByKey); @@ -242,13 +287,28 @@ 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 - return value is int ? value.toDouble() : value is String ? double.tryParse(value) ?? 0.0 : 0.0; - }) - .fold(0.0, (prev, element) => prev + element); + 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; + }).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); @@ -263,7 +323,7 @@ class ChartWidget extends StatelessWidget { ), textAlign: TextAlign.center, ), - SizedBox(height: 5), + SizedBox(height: 15), Text( chartData['chart_sub_heading'] ?? '', style: TextStyle( @@ -272,8 +332,7 @@ class ChartWidget extends StatelessWidget { ), textAlign: TextAlign.center, ), - SizedBox(height: 40), - + SizedBox(height: 70), Expanded( child: ValueListenableBuilder( valueListenable: touchedIndex, @@ -299,30 +358,33 @@ class ChartWidget extends StatelessWidget { ), ), ); - }, - ), ), - SizedBox(height:60), + SizedBox(height: 65), Flexible( + // child: SingleChildScrollView( + // scrollDirection: Axis.horizontal, + // child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Container( - // constraints: - // BoxConstraints(minHeight: 5), // Allow dynamic height + constraints: + BoxConstraints(minHeight: 3), // Allow dynamic height child: Padding( padding: const EdgeInsets.only( left: 0.0, right: 0.0, bottom: 8.0, top: 20.0), child: Wrap( - // spacing: 12, - // runSpacing: 8, + spacing: 12, + runSpacing: 8, children: generateIndicators(chartData, chartData['group_by']), ), ), ), ), + + // ), ), ], ); @@ -360,7 +422,7 @@ class ChartWidget extends StatelessWidget { ), textAlign: TextAlign.center, ), - SizedBox(height: 15), + SizedBox(height: 15), AspectRatio( aspectRatio: 1.5, child: BarChart( @@ -372,11 +434,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 @@ -534,7 +596,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) @@ -571,10 +633,9 @@ 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) { @@ -596,8 +657,7 @@ class ChartWidget extends StatelessWidget { print('Unknown format: $timePeriod'); return timePeriod; // Keep it as is } - }) - .toSet(); + }).toSet(); print("Unique X Values: $uniqueXValues"); @@ -606,18 +666,30 @@ 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"); @@ -629,15 +701,12 @@ 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: [ @@ -671,10 +740,9 @@ class ChartWidget extends StatelessWidget { // 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( @@ -924,11 +992,61 @@ class ChartWidget extends StatelessWidget { List xAxisData = []; List yAxisData = []; + 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 yValue = entry['ObsValue']['Value']; + var xadditionalgroup = + chartData['chart_type_json']['additional_x_group']; + + print('chartData response: ${chartData['response']}'); + + print('xValue-$xValue'); + print('Xadditionalt-$xTimePeriod'); + print('xadditionalgroup-$xadditionalgroup'); + print('yValue-$yValue'); + + 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; + + // 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; + + // First, sort by TIME_PERIOD. If equal, sort by QUARTER + if (timeA != timeB) { + return timeA.compareTo(timeB); + } else { + return quarterA.compareTo(quarterB); + } + }); + } + + // if (xValue != null && yValue != null) { + // xAxisData.add(xValue.toString()); + // yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); + // } if (xValue != null && yValue != null) { - xAxisData.add(xValue.toString()); + // Check if additional_x_group is "Timeperiod" and concatenate + String xLabel = xValue.toString(); + if (xadditionalgroup == 'TIME_PERIOD' && xTimePeriod != null) { + xLabel = '$xTimePeriod-$xValue'; // Format: Label (TimePeriod) + } + + xAxisData.add(xLabel); yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); } } @@ -959,7 +1077,7 @@ 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, @@ -1004,7 +1122,8 @@ class ChartWidget extends StatelessWidget { : title; return Padding( - padding: const EdgeInsets.only(top: 8.0,left: 25.0), + padding: + const EdgeInsets.only(top: 8.0, left: 55.0), child: SizedBox( width: 60, // Limit width to force wrapping child: Transform.rotate( @@ -1012,36 +1131,43 @@ 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 - ), - textStyle: TextStyle(color: Colors.white), // Change text color + 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: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( - color: Colors.blueGrey[800], // Change background color - borderRadius: BorderRadius.circular(8), // Optional: rounded corners + 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, ), - 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(); @@ -1111,102 +1237,104 @@ 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), - ); - }, - ), - ), - 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()}'), + 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), ); }, - reservedSize: 60, ), ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: (value, meta) { - if (value.toInt() < xAxisData.length) { + 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(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(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, + ), ), ), ), - ), - ); - } - return Container(); - }, - reservedSize: 85, + ); + } + return Container(); + }, + reservedSize: 85, + ), + ), + topTitles: AxisTitles( + sideTitles: + SideTitles(showTitles: false), // Hide top titles + ), + rightTitles: AxisTitles( + sideTitles: + SideTitles(showTitles: false), // Hide right titles ), ), - 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, - ), - ], + 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) { @@ -1218,14 +1346,10 @@ 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]; @@ -1233,7 +1357,8 @@ 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]; } @@ -1255,7 +1380,6 @@ class ChartWidget extends StatelessWidget { // // print('groupedCropsflmutli- $groupedCrops'); - return Center( child: Column(children: [ Text( @@ -1286,8 +1410,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( @@ -1310,27 +1434,31 @@ 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 - ), - 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 ), - child: Tooltip( - message: title, - child: Text( - displayTitle, - softWrap: true, - // style: TextStyle(backgroundColor: Colors.blueGrey[800]), - overflow: TextOverflow.ellipsis, - )), - + 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, + )), + ), ))); // return Transform.rotate( // angle: @@ -1353,7 +1481,8 @@ 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 @@ -1371,7 +1500,8 @@ 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]; @@ -1384,7 +1514,9 @@ 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'); @@ -1431,7 +1563,8 @@ class ChartWidget extends StatelessWidget { response != null && response.spot != null) { // setState(() { - touchedGroupIndex = response.spot!.touchedBarGroupIndex; + touchedGroupIndex = + response.spot!.touchedBarGroupIndex; // }); } else { // setState(() { @@ -1950,7 +2083,6 @@ class ChartWidget extends StatelessWidget { return lineBars; } - /// Function to parse TIME_PERIOD into a EXACT value double parseTimePeriod(String timePeriod) { // Match formats @@ -1959,13 +2091,23 @@ 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('-'); @@ -1977,7 +2119,6 @@ class ChartWidget extends StatelessWidget { throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); } - List lineBarsData(List filteredData, Set groupByValues, String groupByKey) { List lineBars = []; @@ -2042,9 +2183,6 @@ class ChartWidget extends StatelessWidget { print('spots - $spots'); - - - // List spots = filteredData // .where((entry) => entry['ObsKey'][groupByKey] == group) // .map((entry) { @@ -2060,8 +2198,6 @@ class ChartWidget extends StatelessWidget { // return FlSpot(xValue, yValue); // }).toList(); - - print('lineGrp2'); // Add a line for this group lineBars.add( @@ -2106,11 +2242,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( @@ -2123,8 +2259,14 @@ class ChartWidget extends StatelessWidget { String formattedValue; if (value % 10 == 0) { - // Check if the value is in the millions or thousands range - if (value >= 1000000) { + // 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 / 1000000000).toStringAsFixed(0)}B'; + } else if (value >= 1000000) { formattedValue = '${(value / 1000000).toStringAsFixed(0)}M'; } else if (value >= 1000) { formattedValue = '${(value / 1000).toStringAsFixed(0)}k'; @@ -2158,21 +2300,22 @@ 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 Transform.rotate( - angle: -0.5, // Slight rotation to improve readability - child: Text( - value.toInt().toString(), - style: TextStyle(color: Colors.black, fontSize: 12), + return Padding( + padding: const EdgeInsets.only(top: 1.1), + child: Transform.rotate( + angle: 0.0, + // angle: -0.5, // Slight rotation to improve readability + child: Text( + value.toInt().toString(), + style: TextStyle(color: Colors.black, fontSize: 12), + ), ), ); } else { @@ -2515,4 +2658,4 @@ class ChartData { final DateTime? xDateTime; ChartData({this.x, required this.y, this.xDateTime}); -} \ No newline at end of file +} diff --git a/pubspec.yaml b/pubspec.yaml index 164da211..a934bad2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: uae_stat description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness." publish_to: "none" -version: 1.0.20+21 +version: 1.0.23+24 environment: sdk: ">=3.2.3 <4.0.0"