From efb0d386642da93e0aeac1891ee6f5b84fb85702 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Thu, 27 Mar 2025 18:43:32 +0530 Subject: [PATCH] bug fix and forgot password --- android/app/build.gradle | 4 +- android/app/src/main/AndroidManifest.xml | 18 +- lib/config/my_router.dart | 3 +- .../UAE_Numbers/uae_numbers.dart | 8 +- .../auth_verification/forgot_password.dart | 91 +- .../Screens/charts/screens/chart_screen.dart | 48 +- .../Screens/charts/widgets/chart_widget.dart | 923 +++++++++--------- .../routes/auth_routes/login_route.dart | 2 + .../Drawer Items/manage_users.dart | 33 +- .../drawer_routes/custom_drawer_routes.dart | 6 +- pubspec.yaml | 2 +- 11 files changed, 636 insertions(+), 502 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 4d3532ef..4563361f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -20,12 +20,12 @@ if (project.hasProperty('google-services.json')) { def flutterVersionCode = localProperties.getProperty("flutter.versionCode") if (flutterVersionCode == null) { - flutterVersionCode = "43" + flutterVersionCode = "44" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.42" + flutterVersionName = "1.0.43" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 7c97326e..f1091bc0 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,13 +30,27 @@ + + + + + + + + diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index 23a8dff9..52e6906b 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -667,7 +667,8 @@ final GoRouter router = GoRouter( redirect: (context, state) async { if (state.uri.path == '/SessionCheckScreen' || state.uri.path == '/login' || - state.uri.path == '/register') { + state.uri.path == '/register' || + state.uri.path == '/forgot-password/:email') { return null; } diff --git a/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart b/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart index 8438fb8b..a9e03fbc 100644 --- a/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart +++ b/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart @@ -240,7 +240,8 @@ class _UaenumberWidgetState extends ConsumerState { onChanged: (value) { filterData( value); // Call filter function directly on input change - }, + }, // Ensures vertical alignment + // Centers text horizontally decoration: InputDecoration( hintText: AppLocalizations.of(context)!.search, hintStyle: TextStyle(color: Color(0xFFAA8E83)), @@ -261,8 +262,9 @@ class _UaenumberWidgetState extends ConsumerState { // // fit: BoxFit.contain, // ), border: InputBorder.none, - contentPadding: - EdgeInsets.symmetric(vertical: 9, horizontal: 18.0), + // contentPadding: + // EdgeInsets.symmetric(vertical: 9, horizontal: 18.0), + contentPadding: EdgeInsets.zero, ), ), ), diff --git a/lib/presentation/Screens/auth_verification/forgot_password.dart b/lib/presentation/Screens/auth_verification/forgot_password.dart index 9ee944a5..6a01c344 100644 --- a/lib/presentation/Screens/auth_verification/forgot_password.dart +++ b/lib/presentation/Screens/auth_verification/forgot_password.dart @@ -107,6 +107,66 @@ class _ForgotPasswordState extends ConsumerState { return null; } + // Future updatePassword( + // String email, String oldPassword, String newPassword) async { + // print(email); + // try { + // setState(() { + // isLoading = true; + // }); + // // Authenticate as admin + // final adminAuth = await _pb.admins + // .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); + // final token = adminAuth.token; + // + // final headers = { + // 'Authorization': 'Bearer $token', + // }; + // + // // Update password + // await _pb.collection('users').update( + // email, + // body: { + // 'password': newPassword, + // 'passwordConfirm': newPassword, + // }, + // headers: headers, + // ); + // + // setState(() { + // isLoading = false; + // _isPasswordUpdated = true; + // }); + // + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: + // Text(AppLocalizations.of(context)!.password_update_successfully), + // backgroundColor: Colors.green, + // ), + // ); + // + // print('_isPasswordUpdated $_isPasswordUpdated'); + // + // // Navigator.push( + // // context, + // // MaterialPageRoute( + // // builder: (context) => ProfileScreen(userId: userId)), + // // ); + // } catch (e) { + // setState(() { + // isLoading = false; + // }); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text(context.translate( + // 'Failed to update password: $e', 'فشل في تحديث كلمة المرور')), + // backgroundColor: Colors.red, + // ), + // ); + // } + // } + Future updatePassword( String email, String oldPassword, String newPassword) async { try { @@ -122,9 +182,27 @@ class _ForgotPasswordState extends ConsumerState { 'Authorization': 'Bearer $token', }; - // Update password + // Step 1: Find User by Email + final result = await _pb.collection('users').getList( + filter: 'email = "$email"', + headers: headers, + ); + + if (result.items.isEmpty) { + // throw Exception("User not found"); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('User not found'), + backgroundColor: Colors.red, + ), + ); + } + + final userId = result.items.first.id; + + // Step 3: Update Password await _pb.collection('users').update( - email, + userId, body: { 'password': newPassword, 'passwordConfirm': newPassword, @@ -146,19 +224,14 @@ class _ForgotPasswordState extends ConsumerState { ); print('_isPasswordUpdated $_isPasswordUpdated'); - - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => ProfileScreen(userId: userId)), - // ); } catch (e) { setState(() { isLoading = false; }); + ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(context.translate('Failed to update password: $e','فشل في تحديث كلمة المرور')), + content: Text('Failed to update password: $e'), backgroundColor: Colors.red, ), ); diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index b297195c..dd771b50 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -2695,50 +2695,54 @@ class _ChartScreen1State extends ConsumerState { } } -Future shareCurrentPage(BuildContext context, bool _isSharing) async { - if (_isSharing) return; // Prevent multiple taps +Future shareCurrentPage(BuildContext context, bool isSharing) async { + if (isSharing) return; // Prevent multiple taps - _isSharing = true; + isSharing = true; try { final String currentRoute = GoRouterState.of(context).uri.toString(); - final String baseAppLink = 'https://fcsc-a161c.web.app'; + final String baseAppLink = 'https://www.fcsc.com'; final String shareLink = '$baseAppLink$currentRoute'; - final String shareText = 'Check this out!'; - final String svgAssetPath = 'assets/backgrounds/share/fcsc.svg'; + final String shareText = 'Check this out!\n\n$shareLink'; + print('Generated Share Link: $shareLink'); + // Optional: Capture SVG to image + final String svgAssetPath = 'assets/backgrounds/share/fcsc.svg'; final screenshotController = ScreenshotController(); final svgWidget = SvgPicture.asset( svgAssetPath, width: 200, height: 200, ); + final Uint8List? capturedImage = await screenshotController.captureFromWidget( Material(child: svgWidget), ); if (capturedImage == null) { - throw Exception('Failed to capture SVG as image'); + print('SVG capture failed, proceeding without image.'); + await Share.share(shareText, subject: 'App Link'); + } else { + final directory = await getTemporaryDirectory(); + final file = File('${directory.path}/share_image.png'); + await file.writeAsBytes(capturedImage); + + await Share.shareXFiles( + [XFile(file.path)], + text: shareText, + subject: 'Shared Content', + ); + + await file.delete(); } - - final directory = await getTemporaryDirectory(); - final file = File('${directory.path}/share.svg'); - await file.writeAsBytes(capturedImage); - - await Share.shareXFiles( - [XFile(file.path)], - text: '$shareText\n$shareLink', - subject: 'Shared Content', - ); - - await file.delete(); } catch (e) { - print("Error sharing file: $e"); + print("Error sharing content: $e"); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error sharing: $e')), + SnackBar(content: Text('Error sharing: ${e.toString()}')), ); } finally { - _isSharing = false; // Reset flag after sharing completes + isSharing = false; // Reset flag } } diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index 195daf1a..5204940f 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:uae_stat/domain/use_cases/language.dart'; // import 'package:syncfusion_flutter_charts/charts.dart'; class ChartWidget extends StatelessWidget { @@ -204,12 +205,11 @@ class ChartWidget extends StatelessWidget { return chartData['response'] .where((entry) => entry['ObsKey'][groupByKey] == groupByValue) .map((entry) { - return ChartData( - x: entry['ObsKey']['TIME_PERIOD'], - y: double.tryParse(entry['ObsValue']['Value']) ?? 0.0, - ); - }) - .toList(); + return ChartData( + x: entry['ObsKey']['TIME_PERIOD'], + y: double.tryParse(entry['ObsValue']['Value']) ?? 0.0, + ); + }).toList(); } List parseColumnChartData(dynamic chartData) { @@ -380,7 +380,8 @@ class ChartWidget extends StatelessWidget { // ]; // } - List generateIndicators(dynamic chartData, double totalValue) { + List generateIndicators( + dynamic chartData, double totalValue, BuildContext context) { var groupByKeyValue; if (chartData['chart_type_json']['chart_type'] == 'bar_chart_horizontal' || chartData['chart_type_json']['chart_type'] == 'horizontal_rotate') { @@ -412,50 +413,83 @@ class ChartWidget extends StatelessWidget { } // double percentage = (value / totalValue) * 100; - String percentage = - (totalValue > 0) - ? ((value / totalValue) * 100).toStringAsFixed(1) - : "0.0"; + String percentage = (totalValue > 0) + ? ((value / totalValue) * 100).toStringAsFixed(1) + : "0.0"; // bool isTouched = index == touchedIndex; + // return Wrap( + // alignment: WrapAlignment.center, + // spacing: 12, + // runSpacing: 8, + // children: [ + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Container( + // width: 10, + // height: 10, + // decoration: BoxDecoration( + // color: uniqueColors[index % uniqueColors.length], + // shape: BoxShape.circle, + // ), + // ), + // SizedBox(width: 8), + // Flexible( + // child: Text( + // context.translate( + // '$title -- $percentage%', + // '$title -- %$percentage', + // ), + // textAlign: TextAlign.start, + // style: TextStyle(fontSize: 12), + // softWrap: true, + // maxLines: 2, // Allows wrapping within two lines + // overflow: TextOverflow.ellipsis, // Prevents overflow + // ), + // ), + // ], + // ), + // ], + // ); + return Row( - mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, // Aligns dot to text start children: [ Container( width: 10, height: 10, + margin: EdgeInsets.only(top: 4), // Adjust to align with text decoration: BoxDecoration( color: uniqueColors[index % uniqueColors.length], shape: BoxShape.circle, ), ), SizedBox(width: 8), - TooltipTheme( - data: TooltipThemeData( - decoration: BoxDecoration( - color: Colors.blueGrey[800], // Change background color - borderRadius: BorderRadius.circular( - 8, - ), // Optional: rounded corners + Expanded( + child: TooltipTheme( + data: TooltipThemeData( + decoration: BoxDecoration( + color: Colors.blueGrey[800], // Change background color + borderRadius: BorderRadius.circular(8), + ), + textStyle: TextStyle(color: Colors.white), ), - 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: 250), + child: Tooltip( + message: title, // Full text on hover child: Text( - '$title -- $percentage%', + context.translate( + '$title -- $percentage%', + '$title -- %$percentage', + ), style: TextStyle(fontSize: 12), softWrap: true, maxLines: 2, - // overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow ), ), ), ), - SizedBox(width: 5), ], ); }).toList(); @@ -618,17 +652,15 @@ class ChartWidget extends StatelessWidget { ), ); case 'pie_chart': - double totalValue = chartData['response'] - .map((entry) { - var value = entry['ObsValue']['Value']; - // print('Processing value: $value, type: ${value.runtimeType}'); - return (value is num) - ? value.toDouble() - : value is String + double totalValue = chartData['response'].map((entry) { + var value = entry['ObsValue']['Value']; + // 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); + }).fold(0.0, (prev, element) => prev + element); ValueNotifier touchedIndex = ValueNotifier(null); @@ -665,10 +697,8 @@ class ChartWidget extends StatelessWidget { touchCallback: (FlTouchEvent event, pieTouchResponse) { if (pieTouchResponse?.touchedSection != null && event is! FlTapUpEvent) { - touchedIndex.value = - pieTouchResponse! - .touchedSection! - .touchedSectionIndex; + touchedIndex.value = pieTouchResponse! + .touchedSection!.touchedSectionIndex; } else { touchedIndex.value = null; // Reset when not touching @@ -704,7 +734,8 @@ class ChartWidget extends StatelessWidget { child: Column( // Change Row to Column crossAxisAlignment: CrossAxisAlignment.start, - children: generateIndicators(chartData, totalValue), + children: + generateIndicators(chartData, totalValue, context), ), ), ), @@ -870,48 +901,47 @@ class ChartWidget extends StatelessWidget { child: Wrap( spacing: 10, // Horizontal spacing between items runSpacing: 5, // Vertical spacing between rows - children: - chunkedGroupByValues.expand((chunk) { - return chunk.map((group) { - List groupByValuesList = groupByValues.toList(); - int index = groupByValuesList.indexOf(group); - Color groupColor = _getColorForGroup(index); + children: chunkedGroupByValues.expand((chunk) { + return chunk.map((group) { + List groupByValuesList = groupByValues.toList(); + int index = groupByValuesList.indexOf(group); + Color groupColor = _getColorForGroup(index); - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 10, - height: 10, - decoration: BoxDecoration( - color: groupColor, - shape: BoxShape.circle, - ), - ), - SizedBox(width: 5), - Tooltip( - message: group, - waitDuration: Duration(milliseconds: 500), - showDuration: Duration(seconds: 2), - decoration: BoxDecoration( - color: Colors.black, - // color: Colors.blueGrey[900], - borderRadius: BorderRadius.circular(4), - ), - textStyle: TextStyle(color: Colors.white), - child: Text( - group, - // group.length > 10 - // ? '${group.substring(0, 10)}...' - // : group, - // overflow: TextOverflow.ellipsis, - style: TextStyle(fontSize: 11), - ), - ), - ], - ); - }).toList(); - }).toList(), + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: groupColor, + shape: BoxShape.circle, + ), + ), + SizedBox(width: 5), + Tooltip( + message: group, + waitDuration: Duration(milliseconds: 500), + showDuration: Duration(seconds: 2), + decoration: BoxDecoration( + color: Colors.black, + // color: Colors.blueGrey[900], + borderRadius: BorderRadius.circular(4), + ), + textStyle: TextStyle(color: Colors.white), + child: Text( + group, + // group.length > 10 + // ? '${group.substring(0, 10)}...' + // : group, + // overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 11), + ), + ), + ], + ); + }).toList(); + }).toList(), ), ), ], @@ -938,13 +968,12 @@ class ChartWidget extends StatelessWidget { print('LnTrnd1'); // Extract all years from the chart data - List years = - (chartData['response'] as List) - .map( - (entry) => - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, - ) - .toList(); + List years = (chartData['response'] as List) + .map( + (entry) => + int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, + ) + .toList(); // Sort in ascending order years.sort(); @@ -974,10 +1003,9 @@ class ChartWidget extends StatelessWidget { // Filter chart data to only include entries within the last 5 years List filteredData = (chartData['response'] as List).where((entry) { - int year = - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; - return year >= minYear && year <= maxYear; - }).toList(); + int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; + return year >= minYear && year <= maxYear; + }).toList(); print('LnTrnd2 $filteredData'); // Set uniqueXValues = filteredData @@ -985,32 +1013,31 @@ 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 - print('TIME_PERIOD- $timePeriod'); + Set uniqueXValues = filteredData.map((entry) { + String? timePeriod = + entry['ObsKey']['TIME_PERIOD']; // Nullable String + print('TIME_PERIOD- $timePeriod'); - if (timePeriod == null) { - print('TIME_PERIOD is null'); - return ''; // Or handle the null case appropriately - } + if (timePeriod == null) { + print('TIME_PERIOD is null'); + return ''; // Or handle the null case appropriately + } - // Check format using regex - if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) { - print('Year format detected: $timePeriod'); - return timePeriod; // Year only - } else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) { - print('Year-Month format detected: $timePeriod'); - return timePeriod; // Year-Month - } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { - print('Year-MonthAbbr format detected: $timePeriod'); - return timePeriod; // Year-MonthAbbr - } else { - print('Unknown format: $timePeriod'); - return timePeriod; // Keep it as is - } - }).toSet(); + // Check format using regex + if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) { + print('Year format detected: $timePeriod'); + return timePeriod; // Year only + } else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) { + print('Year-Month format detected: $timePeriod'); + return timePeriod; // Year-Month + } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { + print('Year-MonthAbbr format detected: $timePeriod'); + return timePeriod; // Year-MonthAbbr + } else { + print('Unknown format: $timePeriod'); + return timePeriod; // Keep it as is + } + }).toSet(); print("Unique X Values: $uniqueXValues"); @@ -1050,11 +1077,10 @@ class ChartWidget extends StatelessWidget { throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); } - Set uniqueXValuesProcessed = - uniqueXValues - .where((value) => value.isNotEmpty) // Remove any empty strings - .map(parseTimePeriod) - .toSet(); + Set uniqueXValuesProcessed = uniqueXValues + .where((value) => value.isNotEmpty) // Remove any empty strings + .map(parseTimePeriod) + .toSet(); print('Processed X Values: $uniqueXValuesProcessed'); print('LnTrnd2.1'); @@ -1150,21 +1176,20 @@ class ChartWidget extends StatelessWidget { child: Wrap( spacing: 12, runSpacing: 8, - children: - groupByValues.map((group) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 12, - height: 12, - color: groupColorMap[group], - ), - SizedBox(width: 6), - Text(group, style: TextStyle(fontSize: 14)), - ], - ); - }).toList(), + children: groupByValues.map((group) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 12, + height: 12, + color: groupColorMap[group], + ), + SizedBox(width: 6), + Text(group, style: TextStyle(fontSize: 14)), + ], + ); + }).toList(), ), ), ], @@ -1185,13 +1210,12 @@ class ChartWidget extends StatelessWidget { // } // Extract all years from the chart data - List years = - (chartData['response'] as List) - .map( - (entry) => - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, - ) - .toList(); + List years = (chartData['response'] as List) + .map( + (entry) => + int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, + ) + .toList(); if (years.isEmpty) { // Return an empty chart if no data @@ -1212,17 +1236,15 @@ class ChartWidget extends StatelessWidget { // Filter chart data to include only the selected years List filteredData = (chartData['response'] as List).where((entry) { - int year = - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; - return selectedYears.contains(year); - }).toList(); + int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; + return selectedYears.contains(year); + }).toList(); - Set uniqueXValues = - filteredData - .map( - (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), - ) - .toSet(); + Set uniqueXValues = filteredData + .map( + (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), + ) + .toSet(); var chartBarColors = chartData['chart_bar_color'] ?? {}; Map barColorsMap = {}; @@ -1296,8 +1318,7 @@ class ChartWidget extends StatelessWidget { scrollDirection: Axis.horizontal, // Enable horizontal scrolling padding: const EdgeInsets.only(right: 40, top: 10), child: SizedBox( - width: - (uniqueXValues.length * 50) + + width: (uniqueXValues.length * 50) + 50, // Adjust width dynamically child: LineChart( LineChartData( @@ -1318,21 +1339,20 @@ class ChartWidget extends StatelessWidget { child: Wrap( spacing: 12, runSpacing: 8, - children: - groupByValues.map((group) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 12, - height: 12, - color: groupColorMap[group], - ), - SizedBox(width: 6), - Text(group, style: TextStyle(fontSize: 14)), - ], - ); - }).toList(), + children: groupByValues.map((group) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 12, + height: 12, + color: groupColorMap[group], + ), + SizedBox(width: 6), + Text(group, style: TextStyle(fontSize: 14)), + ], + ); + }).toList(), ), ), // Chart @@ -1359,13 +1379,12 @@ class ChartWidget extends StatelessWidget { // } // Extract all years from the chart data - List years = - (chartData['response'] as List) - .map( - (entry) => - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, - ) - .toList(); + List years = (chartData['response'] as List) + .map( + (entry) => + int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, + ) + .toList(); if (years.isEmpty) { // Return an empty chart if no data @@ -1386,17 +1405,15 @@ class ChartWidget extends StatelessWidget { // Filter chart data to include only the selected years List filteredData = (chartData['response'] as List).where((entry) { - int year = - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; - return selectedYears.contains(year); - }).toList(); + int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; + return selectedYears.contains(year); + }).toList(); - Set uniqueXValues = - filteredData - .map( - (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), - ) - .toSet(); + Set uniqueXValues = filteredData + .map( + (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), + ) + .toSet(); print('uniqueXValuesLineTrend2- $uniqueXValues'); @@ -1456,8 +1473,7 @@ class ChartWidget extends StatelessWidget { scrollDirection: Axis.horizontal, // Enable horizontal scrolling padding: const EdgeInsets.only(right: 40, top: 20), child: SizedBox( - width: - (uniqueXValues.length * 50) + + width: (uniqueXValues.length * 50) + 50, // Adjust width dynamically child: LineChart( LineChartData( @@ -1516,13 +1532,11 @@ class ChartWidget extends StatelessWidget { int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0; // Extract QUARTER and convert "Q1", "Q2", etc. to numeric values - int quarterA = - int.tryParse( + int quarterA = int.tryParse( a['ObsKey']['QUARTER'].toString().replaceAll('Q', ''), ) ?? 0; - int quarterB = - int.tryParse( + int quarterB = int.tryParse( b['ObsKey']['QUARTER'].toString().replaceAll('Q', ''), ) ?? 0; @@ -1536,22 +1550,44 @@ class ChartWidget extends StatelessWidget { }); } + print('chartData response sort: ${chartData['response']}'); + // if (xValue != null && yValue != null) { // xAxisData.add(xValue.toString()); // yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); // } - if (xValue != null && yValue != null) { - // Check if additional_x_group is "Timeperiod" and concatenate + // if (xValue != null && yValue != null) { + // // 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); + // // yAxisLabels.add(unitMsr ?? ''); + // } + } + 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']; + + if (xValue != null) { String xLabel = xValue.toString(); if (xadditionalgroup == 'TIME_PERIOD' && xTimePeriod != null) { xLabel = '$xTimePeriod-$xValue'; // Format: Label (TimePeriod) } - xAxisData.add(xLabel); + } + if (yValue != null) { yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); - // yAxisLabels.add(unitMsr ?? ''); } } + print('xAxisData $xAxisData'); + print('yAxisData $yAxisData'); return Column( children: [ Text( @@ -1581,26 +1617,23 @@ class ChartWidget extends StatelessWidget { constraints: BoxConstraints( minWidth: screenWidth, // Ensure it at least fills available width - maxWidth: - chartWidth > screenWidth - ? chartWidth - : screenWidth, // Prevent non-normalized constraints + maxWidth: chartWidth > screenWidth + ? chartWidth + : screenWidth, // Prevent non-normalized constraints ), child: Center( child: SizedBox( - width: - xAxisData.length * + width: xAxisData.length * (40 + 10), // Bar width + manual spacing child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, - maxY: - yAxisData.isNotEmpty - ? yAxisData.reduce( - (a, b) => a > b ? a : b, - ) * - 1.2 - : 10, + maxY: yAxisData.isNotEmpty + ? yAxisData.reduce( + (a, b) => a > b ? a : b, + ) * + 1.2 + : 10, // barTouchData: BarTouchData( // enabled: true, // touchCallback: (FlTouchEvent event, barTouchResponse) { @@ -1625,8 +1658,8 @@ class ChartWidget extends StatelessWidget { enabled: false, handleBuiltInTouches: false, touchTooltipData: BarTouchTooltipData( - getTooltipColor: - (group) => Colors.transparent, + getTooltipColor: (group) => + Colors.transparent, // fitInsideHorizontally: true, // fitInsideVertically: true, // tooltipPadding: const EdgeInsets.all(8), @@ -1648,10 +1681,10 @@ class ChartWidget extends StatelessWidget { number_format != null && chartConversion.isNotEmpty) ? formatNumberConversion( - rod.toY, - chartConversion, - number_format, - ) // If condition is true + rod.toY, + chartConversion, + number_format, + ) // If condition is true : formatNumber(rod.toY), const TextStyle( color: Colors.black, @@ -1666,13 +1699,12 @@ class ChartWidget extends StatelessWidget { leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: false, - interval: - (yAxisData.isNotEmpty - ? yAxisData.reduce( - (a, b) => a > b ? a : b, - ) / - 5 - : 1), + interval: (yAxisData.isNotEmpty + ? yAxisData.reduce( + (a, b) => a > b ? a : b, + ) / + 5 + : 1), getTitlesWidget: (value, meta) { return Padding( padding: const EdgeInsets.only( @@ -1691,10 +1723,12 @@ class ChartWidget extends StatelessWidget { getTitlesWidget: (value, meta) { if (value.toInt() < xAxisData.length) { String title = xAxisData[value.toInt()]; - String displayTitle = - title.length > 10 - ? title.substring(0, 10) + '...' - : title; + String displayTitle = title.length > 10 + ? title.substring(0, 10) + '...' + : title; + print('barChartVALUECHECKTITLE $title'); + print( + 'barChartVALUECHECK $displayTitle'); return Padding( padding: const EdgeInsets.only( @@ -1711,13 +1745,12 @@ class ChartWidget extends StatelessWidget { child: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( - color: - Colors - .blueGrey[800], // Change background color + color: Colors.blueGrey[ + 800], // Change background color borderRadius: BorderRadius.circular( - 8, - ), // Optional: rounded corners + 8, + ), // Optional: rounded corners ), textStyle: TextStyle( color: Colors.white, @@ -1726,14 +1759,13 @@ class ChartWidget extends StatelessWidget { child: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( - color: - Colors - .black, // Change background color + color: Colors + .black, // Change background color // color: Colors.blueGrey[800], // Change background color borderRadius: BorderRadius.circular( - 8, - ), // Optional: rounded corners + 8, + ), // Optional: rounded corners ), textStyle: TextStyle( color: Colors.white, @@ -1844,10 +1876,9 @@ class ChartWidget extends StatelessWidget { }); // If no valid TIME_PERIOD with a month is found, return original response - List> finalData = - sortedData.isNotEmpty - ? sortedData - : List.from(chartData['response']); + List> finalData = sortedData.isNotEmpty + ? sortedData + : List.from(chartData['response']); for (var entry in finalData) { var xValue = entry['ObsKey'][groupByKey]; @@ -1908,10 +1939,10 @@ class ChartWidget extends StatelessWidget { chartConversion.isNotEmpty && number_format != null) ? formatNumberConversion( - rod.toY, - chartConversion, - number_format, - ) + rod.toY, + chartConversion, + number_format, + ) : formatNumber(rod.toY), TextStyle( color: Colors.black, @@ -1926,10 +1957,9 @@ class ChartWidget extends StatelessWidget { leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: false, - interval: - (yAxisData.isNotEmpty - ? yAxisData.reduce((a, b) => a > b ? a : b) / 5 - : 1), + 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), @@ -1994,10 +2024,9 @@ class ChartWidget extends StatelessWidget { barsSpace: 20, barRods: [ BarChartRodData( - toY: - (yAxisData[index] == 0) - ? 0.0001 - : yAxisData[index], + toY: (yAxisData[index] == 0) + ? 0.0001 + : yAxisData[index], // color: Colors.blueAccent, color: uniqueColors[1], borderRadius: BorderRadius.circular(4), @@ -2132,17 +2161,16 @@ class ChartWidget extends StatelessWidget { ), // Dynamically calculate max Y // barGroups: _buildHorizontalRotateBarGroups( // chartData, groupByValues), // Build bar groups - barGroups: - hasBarColors - ? _buildHorizontalRotateBarGroupsBarColors( - chartData, - groupByValues, - parsedChartBarColors, - ) - : _buildHorizontalRotateBarGroups( - chartData, - groupByValues, - ), + barGroups: hasBarColors + ? _buildHorizontalRotateBarGroupsBarColors( + chartData, + groupByValues, + parsedChartBarColors, + ) + : _buildHorizontalRotateBarGroups( + chartData, + groupByValues, + ), titlesData: FlTitlesData( leftTitles: AxisTitles( @@ -2159,10 +2187,9 @@ class ChartWidget extends StatelessWidget { value.toInt(), ); - String displayTitle = - title.length > 10 - ? title.substring(0, 10) + '...' - : title; + String displayTitle = title.length > 10 + ? title.substring(0, 10) + '...' + : title; return Padding( padding: const EdgeInsets.only( @@ -2177,14 +2204,13 @@ class ChartWidget extends StatelessWidget { child: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( - color: - Colors - .black, // Change background color + color: Colors + .black, // Change background color // color: Colors.blueGrey[800], // Change background color borderRadius: BorderRadius.circular( - 8, - ), // Optional: rounded corners + 8, + ), // Optional: rounded corners ), textStyle: TextStyle( color: Colors.white, @@ -2273,10 +2299,9 @@ class ChartWidget extends StatelessWidget { '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'); @@ -2331,8 +2356,8 @@ class ChartWidget extends StatelessWidget { ); case 'horizontal_rotate': - String cropKey = - chartData['chart_type_json']['y_sub_group']; // Dynamically get crop key + String cropKey = chartData['chart_type_json'] + ['y_sub_group']; // Dynamically get crop key // Group crops by CROP_TYPE Map> groupedCrops = {}; @@ -2551,10 +2576,8 @@ class ChartWidget extends StatelessWidget { enabled: false, // Enable touch to show tooltip handleBuiltInTouches: false, touchTooltipData: BarTouchTooltipData( - getTooltipColor: - (group) => - Colors - .transparent, // Light background for visibility + getTooltipColor: (group) => Colors + .transparent, // Light background for visibility tooltipHorizontalAlignment: FLHorizontalAlignment.center, tooltipRoundedRadius: @@ -2574,6 +2597,18 @@ class ChartWidget extends StatelessWidget { String crop = groupedCrops[cropType]![rodIndex]; double value = rod.toY; + // Show tooltip for zero values + if (value == 0) { + return BarTooltipItem( + '0', // Display "0" instead of hiding + textAlign: TextAlign.right, + const TextStyle( + color: Colors.black, + fontSize: 12, + ), + ); + } + // Format values dynamically // String formattedValue = value >= 1e6 // ? '${(value / 1e6).toStringAsFixed(1)}M' @@ -2593,7 +2628,7 @@ class ChartWidget extends StatelessWidget { 0, ); // for values smaller than 1000 } - + print('formattedValue00 $formattedValue'); return BarTooltipItem( formattedValue, textAlign: TextAlign.right, @@ -2690,17 +2725,16 @@ class ChartWidget extends StatelessWidget { // barGroups: _buildHorizontalRotateBarGroups( // chartData, groupByValues), - barGroups: - hasBarColors - ? _buildHorizontalRotateBarGroupsBarColors( - chartData, - groupByValues, - parsedChartBarColors, - ) - : _buildHorizontalRotateBarGroups( - chartData, - groupByValues, - ), + barGroups: hasBarColors + ? _buildHorizontalRotateBarGroupsBarColors( + chartData, + groupByValues, + parsedChartBarColors, + ) + : _buildHorizontalRotateBarGroups( + chartData, + groupByValues, + ), alignment: BarChartAlignment.spaceAround, ), @@ -2923,42 +2957,39 @@ class ChartWidget extends StatelessWidget { // return FlSpot(xValue, yValue); // }).toList(); - List spots = - filteredData - .where((entry) => entry['ObsKey'][groupByKey] == group) - .map((entry) { - String timePeriod = entry['ObsKey']['TIME_PERIOD']; - print("FindTimePeriod: $timePeriod"); + List spots = filteredData + .where((entry) => entry['ObsKey'][groupByKey] == group) + .map((entry) { + String timePeriod = entry['ObsKey']['TIME_PERIOD']; + print("FindTimePeriod: $timePeriod"); - // Use the timePeriod directly as a string for x-axis - double xValue = parseTimePeriod(timePeriod); - print('spotss $xValue'); + // Use the timePeriod directly as a string for x-axis + double xValue = parseTimePeriod(timePeriod); + print('spotss $xValue'); - // double yValue = double.parse(entry['ObsValue']['Value']); - double yValue; - var value = entry['ObsValue']['Value']; + // double yValue = double.parse(entry['ObsValue']['Value']); + double yValue; + var value = entry['ObsValue']['Value']; - print('LineTrend $value'); + print('LineTrend $value'); - if (value is int) { - yValue = value.toDouble(); - } else if (value is double) { - yValue = value; - } else if (value is String) { - yValue = - double.tryParse(value) ?? - 0.0; // Handle invalid strings safely - } else { - throw Exception( - "Unexpected value type: ${value.runtimeType}", - ); - } - print('LineTrendX $xValue'); - print('LineTrendY $yValue'); - return FlSpot(xValue, yValue); - }) - .toList() - ..sort((a, b) => a.x.compareTo(b.x)); + if (value is int) { + yValue = value.toDouble(); + } else if (value is double) { + yValue = value; + } else if (value is String) { + yValue = + double.tryParse(value) ?? 0.0; // Handle invalid strings safely + } else { + throw Exception( + "Unexpected value type: ${value.runtimeType}", + ); + } + print('LineTrendX $xValue'); + print('LineTrendY $yValue'); + return FlSpot(xValue, yValue); + }).toList() + ..sort((a, b) => a.x.compareTo(b.x)); print('spots - $spots'); @@ -3014,10 +3045,9 @@ class ChartWidget extends StatelessWidget { getTooltipColor: (spot) => Colors.black, getTooltipItems: (List lineBarsSpot) { return lineBarsSpot.map((lineBarSpot) { - Color lineColor = - lineBarSpot.bar is LineChartBarData - ? (lineBarSpot.bar).color ?? Colors.white - : Colors.white; // Extract bar color safely + Color lineColor = lineBarSpot.bar is LineChartBarData + ? (lineBarSpot.bar).color ?? Colors.white + : Colors.white; // Extract bar color safely return LineTooltipItem( '', const TextStyle(), @@ -3030,16 +3060,15 @@ class ChartWidget extends StatelessWidget { ), TextSpan( // text: formatNumber(lineBarSpot.y), - text: - (chartConversion != null && - chartConversion.isNotEmpty && - number_format != null) - ? formatNumberConversion( - lineBarSpot.y, - chartConversion, - number_format, - ) - : formatNumber(lineBarSpot.y), + text: (chartConversion != null && + chartConversion.isNotEmpty && + number_format != null) + ? formatNumberConversion( + lineBarSpot.y, + chartConversion, + number_format, + ) + : formatNumber(lineBarSpot.y), // text: ' ${lineBarSpot.y}', // Keep the value white style: const TextStyle(color: Colors.white), ), @@ -3128,10 +3157,10 @@ class ChartWidget extends StatelessWidget { return FlGridData( show: false, drawVerticalLine: true, - getDrawingHorizontalLine: - (value) => FlLine(color: Colors.grey, strokeWidth: 1), - getDrawingVerticalLine: - (value) => FlLine(color: Colors.grey, strokeWidth: 1), + getDrawingHorizontalLine: (value) => + FlLine(color: Colors.grey, strokeWidth: 1), + getDrawingVerticalLine: (value) => + FlLine(color: Colors.grey, strokeWidth: 1), ); } @@ -3568,65 +3597,62 @@ class ChartWidget extends StatelessWidget { String groupValue = groupByValues.elementAt(i); // Filter data for the current group (grouping by CROP_TYPE) - List groupData = - responseData.where((entry) { - return entry['ObsKey'][groupByKeyValueData] == groupValue; - }).toList(); + List groupData = responseData.where((entry) { + return entry['ObsKey'][groupByKeyValueData] == groupValue; + }).toList(); // Create BarChartRodData for each bar in the group - List barRods = - groupData.map((data) { - // Ensure to retrieve and parse 'ObsValue' value (which should be a double) - double value = - double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; - // double minBarHeight = 0.5; - print('multi_bar1.1'); - // final List uniqueColorsForTwo = [ - // Color(0xFF648CBA), - // Color(0xFF90B0D5), - // ]; + List barRods = groupData.map((data) { + // Ensure to retrieve and parse 'ObsValue' value (which should be a double) + double value = + double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; + double minBarHeight = 0.1; + print('multi_bar1.1'); + // final List uniqueColorsForTwo = [ + // Color(0xFF648CBA), + // Color(0xFF90B0D5), + // ]; - // Use bodyColor instead of hardcoded colors + // Use bodyColor instead of hardcoded colors - final barColor; - if (chartData['dataset'] == 'general_education' || - chartData['dataset'] == 'higher_education' || - chartData['dataset'] == 'air_transport' || - chartData['dataset'] == 'labour_force' || - chartData['dataset'] == 'gdp' || - chartData['dataset'] == 'hotels' || - chartData['dataset'] == 'hotel_guests' || - chartData['dataset'] == 'health_services' || - chartData['dataset'] == 'clinics') { - barColor = - uniqueColorsForTwo[colorIndex % uniqueColorsForTwo.length]; - colorIndex++; - } else if (chartData['dataset'] == 'cropsk') { - barColor = - uniqueColorsForThree[colorIndex % - uniqueColorsForThree.length]; - colorIndex++; - } else if (chartData['dataset'] == 'oil_and_gas') { - barColor = - uniqueColorsForFour[colorIndex % uniqueColorsForFour.length]; - colorIndex++; - } else { - barColor = uniqueColors[colorIndex % uniqueColors.length]; - colorIndex++; - } + final barColor; + if (chartData['dataset'] == 'general_education' || + chartData['dataset'] == 'higher_education' || + chartData['dataset'] == 'air_transport' || + chartData['dataset'] == 'labour_force' || + chartData['dataset'] == 'gdp' || + chartData['dataset'] == 'hotels' || + chartData['dataset'] == 'hotel_guests' || + chartData['dataset'] == 'health_services' || + chartData['dataset'] == 'clinics') { + barColor = uniqueColorsForTwo[colorIndex % uniqueColorsForTwo.length]; + colorIndex++; + } else if (chartData['dataset'] == 'cropsk') { + barColor = + uniqueColorsForThree[colorIndex % uniqueColorsForThree.length]; + colorIndex++; + } else if (chartData['dataset'] == 'oil_and_gas') { + barColor = + uniqueColorsForFour[colorIndex % uniqueColorsForFour.length]; + colorIndex++; + } else { + barColor = uniqueColors[colorIndex % uniqueColors.length]; + colorIndex++; + } - return BarChartRodData( - toY: value, // Use the parsed value - color: barColor, // Dynamic color - width: 20, + return BarChartRodData( + // toY: value, + toY: value == 0 ? minBarHeight : value, // Use the parsed value + color: barColor, // Dynamic color + width: 20, - // backDrawRodData: BackgroundBarChartRodData( - // show: true, - // toY: 400000, - // color: Colors.grey.shade300, - // ), - ); - }).toList(); + // backDrawRodData: BackgroundBarChartRodData( + // show: true, + // toY: 400000, + // color: Colors.grey.shade300, + // ), + ); + }).toList(); // Add BarChartGroupData for the group barGroups.add( @@ -3677,10 +3703,9 @@ class ChartWidget extends StatelessWidget { String groupValue = groupByValues.elementAt(i); // Filter data for the current group - List groupData = - responseData.where((entry) { - return entry['ObsKey'][groupByKeyValueData1] == groupValue; - }).toList(); + List groupData = responseData.where((entry) { + return entry['ObsKey'][groupByKeyValueData1] == groupValue; + }).toList(); Map genderMapping = { 'ذكر': 'Male', // Arabic for Male @@ -3698,39 +3723,37 @@ class ChartWidget extends StatelessWidget { }); // Create BarChartRodData for each bar in the group - List barRods = - groupData.map((data) { - double value = - double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; + List barRods = groupData.map((data) { + double value = + double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; - // Get gender-based color - String gender = data['ObsKey']['GENDER'] ?? ""; - // Convert Arabic gender to English if necessary - String normalizedGender = genderMapping[gender] ?? gender; + // Get gender-based color + String gender = data['ObsKey']['GENDER'] ?? ""; + // Convert Arabic gender to English if necessary + String normalizedGender = genderMapping[gender] ?? gender; - print('horizontalRotateGender - $gender'); - // Map Arabic gender values to English equivalents + print('horizontalRotateGender - $gender'); + // Map Arabic gender values to English equivalents - // Determine color dynamically - Color barColor; - if (chartData['dataset'] == 'health_services') { - barColor = - uniqueColorsForTwo[colorIndex % - 2]; // Alternate between two colors - colorIndex++; // Update index for next bar - } else { - // barColor = chartBarColors[gender] ?? Colors.grey; // Default gender-based color - barColor = chartBarColors[normalizedGender] ?? Colors.grey; - } + // Determine color dynamically + Color barColor; + if (chartData['dataset'] == 'health_services') { + barColor = uniqueColorsForTwo[ + colorIndex % 2]; // Alternate between two colors + colorIndex++; // Update index for next bar + } else { + // barColor = chartBarColors[gender] ?? Colors.grey; // Default gender-based color + barColor = chartBarColors[normalizedGender] ?? Colors.grey; + } - print('GEG- $gender'); + print('GEG- $gender'); - return BarChartRodData( - toY: value, // Use the parsed value - color: barColor, // Gender-based dynamic color - width: 20, - ); - }).toList(); + return BarChartRodData( + toY: value, // Use the parsed value + color: barColor, // Gender-based dynamic color + width: 20, + ); + }).toList(); // Add BarChartGroupData for the group barGroups.add( @@ -3772,27 +3795,25 @@ Widget _buildChartLegend( alignment: WrapAlignment.center, spacing: 12, runSpacing: 6, - children: - uniqueCropTypes.map((cropType) { - // Color cropColor = parsedChartBarColors[cropType] ?? Colors.grey; // Fetch color for each crop type - int index = uniqueCropTypes.toList().indexOf( + children: uniqueCropTypes.map((cropType) { + // Color cropColor = parsedChartBarColors[cropType] ?? Colors.grey; // Fetch color for each crop type + int index = uniqueCropTypes.toList().indexOf( cropType, ); // Get index for cycling colors - Color cropColor = - parsedChartBarColors.isNotEmpty && - parsedChartBarColors.containsKey(cropType) - ? parsedChartBarColors[cropType]! - : uniqueColors[index % uniqueColors.length]; + Color cropColor = parsedChartBarColors.isNotEmpty && + parsedChartBarColors.containsKey(cropType) + ? parsedChartBarColors[cropType]! + : uniqueColors[index % uniqueColors.length]; - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - CircleAvatar(radius: 6, backgroundColor: cropColor), - const SizedBox(width: 4), - Text(cropType, style: const TextStyle(fontSize: 12)), - ], - ); - }).toList(), + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + CircleAvatar(radius: 6, backgroundColor: cropColor), + const SizedBox(width: 4), + Text(cropType, style: const TextStyle(fontSize: 12)), + ], + ); + }).toList(), ); } diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index 8f5376d6..b991e709 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -702,6 +702,8 @@ class LoginRoute extends HookConsumerWidget { ); final dontHaveAnAccountRegisterBtn = TextButton( onPressed: () => {context.push('/register')}, + // onPressed: () => + // {context.push('/forgot-password/surendar.m@venbainfotech.com')}, child: Text.rich( textAlign: TextAlign.center, TextSpan( diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart index f3ad0035..e047972a 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart @@ -152,7 +152,9 @@ class _ManageUserRouterState extends ConsumerState { isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(AppLocalizations.of(context)!.status_success),), + SnackBar( + content: Text(AppLocalizations.of(context)!.status_success), + ), ); } catch (e) { setState(() { @@ -160,13 +162,16 @@ class _ManageUserRouterState extends ConsumerState { }); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(context.translate('Error updating status: $e','$e خطأ في تحديث الحالة: '))), + SnackBar( + content: Text(context.translate( + 'Error updating status: $e', '$e خطأ في تحديث الحالة: '))), ); } } //Method to show a confirmation dialog when status is changed - Future _showConfirmationDialog(User user, String newStatus,String statusUpdate) async { + Future _showConfirmationDialog( + User user, String newStatus, String statusUpdate) async { print('user $user'); double myheight = MediaQuery.of(context).size.height; @@ -416,8 +421,9 @@ class _ManageUserRouterState extends ConsumerState { // // fit: BoxFit.contain, // ), border: InputBorder.none, - contentPadding: EdgeInsets.symmetric( - vertical: 9, horizontal: 18.0), + // contentPadding: EdgeInsets.symmetric( + // vertical: 9, horizontal: 18.0), + contentPadding: EdgeInsets.zero, ), onChanged: filterUsers, ), @@ -444,7 +450,8 @@ class _ManageUserRouterState extends ConsumerState { SizedBox(height: 15), // Space between icon and text Text( - AppLocalizations.of(context)!.no_result_found, + AppLocalizations.of(context)! + .no_result_found, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, @@ -455,7 +462,9 @@ class _ManageUserRouterState extends ConsumerState { SizedBox(height: 12), // Space between texts FittedBox( child: Text( - context.translate("We couldn't find anything matching your search.",'لم نعثر على أي شيء يطابق بحثك.'), + context.translate( + "We couldn't find anything matching your search.", + 'لم نعثر على أي شيء يطابق بحثك.'), style: TextStyle( fontSize: 18, color: Color(0xFF898C81)), @@ -533,7 +542,9 @@ class _ManageUserRouterState extends ConsumerState { (index) => DataCell( index == 0 ? Text( - AppLocalizations.of(context)!.no_result_found, + AppLocalizations.of( + context)! + .no_result_found, style: TextStyle( fontStyle: FontStyle .italic), @@ -573,7 +584,11 @@ class _ManageUserRouterState extends ConsumerState { print(user); if (newStatus != null) { _showConfirmationDialog( - user, newStatus, statusOptions[newStatus]!,); + user, + newStatus, + statusOptions[ + newStatus]!, + ); } }, ), diff --git a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart index 2b29eb5b..e1e45c43 100644 --- a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart +++ b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart @@ -298,7 +298,7 @@ class _BaseScaffoldState extends ConsumerState { createTargetContent( text: AppLocalizations.of(context)!.mainMenu, alignment: ContentAlign.bottom, - space:55, + space: 55, gap: 55, ), TargetContent( @@ -989,7 +989,9 @@ class _BaseScaffoldState extends ConsumerState { ), ListTile( leading: Icon(Icons.mail_outlined), - title: Text(context.translate('Contact Us', 'اتصل بنا'),), + title: Text( + context.translate('Contact Us', 'اتصل بنا'), + ), onTap: () => context.push('/contact'), ), if (userId != 'guest') diff --git a/pubspec.yaml b/pubspec.yaml index 4b965ae1..914510fe 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.42+43 +version: 1.0.43+44 environment: sdk: ">=3.2.3 <4.0.0"