From 62ba6d52c7ca3bffc92e27aca77655c8333e403d Mon Sep 17 00:00:00 2001 From: Juki-shiba Date: Wed, 11 Jun 2025 18:38:10 +0530 Subject: [PATCH 1/2] competitiveness ph-1 --- .../arm64-v8a/configure_fingerprint.bin | 24 +- .../armeabi-v7a/configure_fingerprint.bin | 24 +- .../6k676t62/x86/configure_fingerprint.bin | 24 +- .../6k676t62/x86_64/configure_fingerprint.bin | 24 +- lib/config/my_router.dart | 6 +- lib/l10n/intl_ar.arb | 1 + .../Detailedcompetitiveness.dart | 281 +++++++++--------- 7 files changed, 189 insertions(+), 195 deletions(-) diff --git a/android/app/.cxx/Debug/6k676t62/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/6k676t62/arm64-v8a/configure_fingerprint.bin index 9f1acb5e..d9056f6c 100644 --- a/android/app/.cxx/Debug/6k676t62/arm64-v8a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/6k676t62/arm64-v8a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Loge c aC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  ̲2b +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  ̲2b ` -^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\android_gradle_build.json  2 ز2g +^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\android_gradle_build.json  2 ز2g e -cC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\android_gradle_build_mini.json  2 粊2T +cC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\android_gradle_build_mini.json  2 粊2T R -PC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\build.ninja  2 Ʊ2X +PC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\build.ninja  2 Ʊ2X V -TC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\build.ninja.txt  2] +TC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\build.ninja.txt  2] [ -YC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\build_file_index.txt  2 S 2^ +YC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\build_file_index.txt  2 S 2^ \ -ZC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\compile_commands.json  2b +ZC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\compile_commands.json  2b ` -^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\compile_commands.json.bin  2 h +^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\compile_commands.json.bin  2 h f -dC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\metadata_generation_command.txt  2 +dC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\metadata_generation_command.txt  2  벊2[ Y -WC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\prefab_config.json  2  ( 첊2` +WC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\prefab_config.json  2  ( 첊2` ^ -\C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\symbol_folder_index.txt  2  S 2W +\C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\arm64-v8a\symbol_folder_index.txt  2  S 2W U -SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/6k676t62/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/6k676t62/armeabi-v7a/configure_fingerprint.bin index 14592bed..771596e7 100644 --- a/android/app/.cxx/Debug/6k676t62/armeabi-v7a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/6k676t62/armeabi-v7a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logg e cC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  啋2d +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ⼓2  啋2d b -`C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\android_gradle_build.json  2 땋2i +`C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\android_gradle_build.json  ⼓2 땋2i g -eC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\android_gradle_build_mini.json  2 2V +eC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\android_gradle_build_mini.json  ⼓2 2V T -RC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\build.ninja  2 ͓2Z +RC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\build.ninja  ⼓2 ͓2Z X -VC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\build.ninja.txt  2_ +VC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\build.ninja.txt  ⼓2_ ] -[C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\build_file_index.txt  2 S 2` +[C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\build_file_index.txt  ⼓2 S 2` ^ -\C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\compile_commands.json  2d +\C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\compile_commands.json  ⼓2d b -`C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\compile_commands.json.bin  2 j +`C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\compile_commands.json.bin  ⼓2 j h -fC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\metadata_generation_command.txt  2 +fC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\metadata_generation_command.txt  ⼓2  2] [ -YC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\prefab_config.json  2  ( 2b +YC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\prefab_config.json  ⼓2  ( 2b ` -^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\symbol_folder_index.txt  2  U 2W +^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\armeabi-v7a\symbol_folder_index.txt  ⼓2  U 2W U -SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  ⼓2  2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/6k676t62/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/6k676t62/x86/configure_fingerprint.bin index 98a269ef..3ff98ec2 100644 --- a/android/app/.cxx/Debug/6k676t62/x86/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/6k676t62/x86/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Log_ ] [C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2\ +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2\ Z -XC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\android_gradle_build.json  2 2a +XC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\android_gradle_build.json  2 2a _ -]C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\android_gradle_build_mini.json  2 2N +]C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\android_gradle_build_mini.json  2 2N L -JC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\build.ninja  2 2R +JC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\build.ninja  2 2R P -NC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\build.ninja.txt  2W +NC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\build.ninja.txt  2W U -SC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\build_file_index.txt  2 S 2X +SC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\build_file_index.txt  2 S 2X V -TC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\compile_commands.json  2\ +TC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\compile_commands.json  2\ Z -XC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\compile_commands.json.bin  2 b +XC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\compile_commands.json.bin  2 b ` -^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\metadata_generation_command.txt  2 +^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\metadata_generation_command.txt  2  2U S -QC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\prefab_config.json  2  ( 2Z +QC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\prefab_config.json  2  ( 2Z X -VC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\symbol_folder_index.txt  2  M 2W +VC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86\symbol_folder_index.txt  2  M 2W U -SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/6k676t62/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/6k676t62/x86_64/configure_fingerprint.bin index 02f709e1..5d08449f 100644 --- a/android/app/.cxx/Debug/6k676t62/x86_64/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/6k676t62/x86_64/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logb ` ^C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  ˋ2_ +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  ˋ2_ ] -[C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\android_gradle_build.json  2 ˋ2d +[C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\android_gradle_build.json  2 ˋ2d b -`C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\android_gradle_build_mini.json  2 ˋ2Q +`C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\android_gradle_build_mini.json  2 ˋ2Q O -MC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\build.ninja  2 ʋ2U +MC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\build.ninja  2 ʋ2U S -QC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\build.ninja.txt  2Z +QC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\build.ninja.txt  2Z X -VC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\build_file_index.txt  2 S ˋ2[ +VC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\build_file_index.txt  2 S ˋ2[ Y -WC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\compile_commands.json  2_ +WC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\compile_commands.json  2_ ] -[C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\compile_commands.json.bin  2 e +[C:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\compile_commands.json.bin  2 e c -aC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\metadata_generation_command.txt  2 +aC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\metadata_generation_command.txt  2  ˋ2X V -TC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\prefab_config.json  2  ( ˋ2] +TC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\prefab_config.json  2  ( ˋ2] [ -YC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\symbol_folder_index.txt  2  P ˋ2W +YC:\flutter code\share\FCSC\android\app\.cxx\Debug\6k676t62\x86_64\symbol_folder_index.txt  2  P ˋ2W U -SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +SC:\flutter\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index 058bb76a..c4c31ad6 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -372,8 +372,8 @@ final GoRouter router = GoRouter( routes: [ GoRoute( path: '/', - // builder: (context, state) => LoginRoute(), - builder: (context, state) => SessionCheckScreen(), + builder: (context, state) => Competitiveness(), + // builder: (context, state) => SessionCheckScreen(), ), // GoRoute( // path: '/', @@ -673,7 +673,7 @@ final GoRouter router = GoRouter( path: '/reportDetail', builder: (context, state) { final report = state.extra as Map; - return ReportDetailPage(report: report); + return ReportDetailPage(); }, ), diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index 7e41b973..fb887af0 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -118,6 +118,7 @@ "new_password_required": "كلمة المرور الجديدة مطلوبة", "old_password_is_required": "كلمة المرور القديمة مطلوبة", "confirm_password_is_required": "تأكيد كلمة المرور مطلوب", + "UAE Competitiveness":"التقارير التنافسيه لدولة الامارات", "kpiCards": "يمكنك عرض بطاقات مؤشرات الأداء الرئيسية التفاعلية والرسوم البيانية لاستكشاف اتجاهات البيانات ومقارنة المقاييس الرئيسية بصريًا", "home_topic": "اختر أي فئة (على سيبل المثال : الاقتصاد، الاجتماعية، البيئة) لاستكشاف مؤشرات الأداء الرئيسية التفصيلية ، التصورات، ورؤى البيانات .", diff --git a/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/Detailedcompetitiveness.dart b/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/Detailedcompetitiveness.dart index 961485a3..2b6001f2 100644 --- a/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/Detailedcompetitiveness.dart +++ b/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/Detailedcompetitiveness.dart @@ -4,209 +4,202 @@ import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class ReportDetailPage extends StatelessWidget { - final Map report; - - const ReportDetailPage({super.key, required this.report}); + const ReportDetailPage({super.key}); @override Widget build(BuildContext context) { - double width = MediaQuery.of(context).size.width; - return BaseScaffold( title: Text( - context.translate('UAE Competitiveness', 'القدرة التنافسية للإمارات'), // Add localization + context.translate( + 'UAE Competitiveness', + 'التقارير التنافسيه لدولة الامارات', + ), style: TextStyle( - fontFamily: context.translate('Roboto', 'NotoKufi'), + fontFamily: context.translate( + 'Roboto', + 'NotoKufi', + ) ), ), - // hasDrawer: false, showBackButton: true, body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Header Section: Report Title and Image - Center( - child: Column( + Container( + padding: EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Expanded( + child: Text( + 'Prosperity Index (2023)', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ), Image.asset( 'assets/competitiveness/solo.png', - height: 80, // Increase size for prominence - ), - const SizedBox(height: 8), - Text( - context.translate('Prosperity Index (2023)', 'مؤشر الازدهار (2023)'), - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - ), + height: 71, + width: 84, ), ], ), ), const SizedBox(height: 24), - // Description Section - Text( - context.translate( - "The Legatum Prosperity Index is published annually by the Legatum Institute. It is a policy-focused report that measures the current state of prosperity since 2007. Using the Prosperity Index framework, nations around the world can assess their strengths and weaknesses in order to determine the economic and strategic choices that need to be made to further build inclusive societies, open economies, and empowered people to drive greater levels of prosperity.", - "يُنشر مؤشر الازدهار الليجاتوم سنويًا من قبل معهد ليجاتوم. إنه تقرير يركز على السياسات ويقيس الحالة الحالية للازدهار منذ عام 2007. باستخدام إطار مؤشر الازدهار، يمكن للدول حول العالم تقييم نقاط قوتها وضعفها لتحديد الخيارات الاقتصادية والاستراتيجية التي يجب اتخاذها لتعزيز بناء مجتمعات شاملة واقتصادات مفتوحة وتمكين الأفراد لدفع مستويات أعلى من الازدهار.", - ), - style: const TextStyle(fontSize: 14), + const Text( + 'The Legatum Prosperity Index is published annually by the Legatum Institute. It is a policy-focused report that measures the current state of prosperity since 2007. Using the Prosperity Index framework, nations around the world can assess their strengths and weaknesses in order to determine the economic and strategic choices that need to be made to further build inclusive societies, open economies, and empowered people to drive greater levels of prosperity.', + style: TextStyle(fontSize: 13), ), const SizedBox(height: 24), - // Ranking Section (Using LeaderCard-like styling) - Wrap( - spacing: 16, - runSpacing: 16, - alignment: WrapAlignment.center, + // Ranking section + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _RankingCard( - title: context.translate('Rank in 2023', 'الترتيب في 2023'), - value: "44", - icon: const Icon(Icons.arrow_downward, color: Colors.red, size: 16), + title: 'Rank in 2023', + value: '44', + icon: const Icon(Icons.arrow_downward, color: Colors.red, size: 25,weight: 50), ), _RankingCard( - title: context.translate('vs. Previous Edition', 'مقارنة بالإصدار السابق'), - value: "41", - icon: const SizedBox.shrink(), // No icon for this + title: 'vs. Previous Edition', + value: '41', + icon: const SizedBox.shrink(), ), ], ), const SizedBox(height: 24), - // Country Rankings Section (Using CategoryButton-like styling) - // Wrap( - // spacing: 16, - // runSpacing: 16, - // alignment: WrapAlignment.center, - // children: [ - // _CountryRankingButton( - // title: context.translate('First Globally: DENMARK', 'الأول عالميًا: الدنمارك'), - // imagePath: 'assets/flags/denmark.png', - // color: const Color(0xFFD7C1AF), - // ), - // _CountryRankingButton( - // title: context.translate('First in GCC: MULTIPLE COUNTRIES', 'الأول في دول الخليج: دول متعددة'), - // imagePath: null, // No specific flag - // color: const Color(0xFFAEC6CF), - // ), - // _CountryRankingButton( - // title: context.translate('First in Arab Countries: UAE', 'الأول في الدول العربية: الإمارات'), - // imagePath: 'assets/flags/uae.png', - // color: const Color(0xFFD7AFAF), - // ), - // ], - // ), + // Country ranking section + _CountryRankingItem( + title: 'First Globally', + country: 'DENMARK', + flagPath: 'assets/country_flags/de.png', + ), + const Divider(), + _CountryRankingItem( + title: 'First in Oman', + country: 'Oman', + flagPath: 'assets/country_flags/fk.png', + ), + const Divider(), + _CountryRankingItem( + title: 'First in Arab Countries', + country: 'UNITED ARAB EMIRATES', + flagPath: 'assets/country_flags/ga.png', + ), ], ), ), ); } } - -// Ranking Card (similar to _LeaderCard) class _RankingCard extends StatelessWidget { final String title; final String value; final Widget icon; const _RankingCard({ - Key? key, required this.title, required this.value, required this.icon, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 160, - child: Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.grey[100], - borderRadius: BorderRadius.circular(12), - ), - child: Column( - children: [ - Text( - title, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 13, - color: Colors.black54, - ), - ), - const SizedBox(height: 4), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - value, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(width: 4), - icon, - ], - ), - ], - ), - ), - ); - } -} - -// Country Ranking Button (similar to _CategoryButton) -class _CountryRankingButton extends StatelessWidget { - final String title; - final String? imagePath; - final Color color; - - const _CountryRankingButton({ - Key? key, - required this.title, - required this.imagePath, - required this.color, - }) : super(key: key); + }); @override Widget build(BuildContext context) { return Container( + margin: const EdgeInsets.symmetric(vertical: 6), width: 160, - height: 70, + padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular(16), + color: Colors.grey[100], + borderRadius: BorderRadius.circular(12), ), - alignment: Alignment.center, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, + child: Column( children: [ - if (imagePath != null) ...[ - Image.asset( - imagePath!, - width: 24, - height: 24, - ), - const SizedBox(width: 8), - ], - Flexible( - child: Text( - title, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 14, + Text( + title, + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 13, color: Colors.black54), + ), + const SizedBox(height: 4), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + value, + style: const TextStyle( + fontSize: 36, + fontWeight: FontWeight.bold, + ), ), - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, + const SizedBox(width: 6), + icon, + ], + ), + ], + ), + ); + } +} +class _CountryRankingItem extends StatelessWidget { + + final String title; + final String country; + final String flagPath; + + const _CountryRankingItem({ + required this.title, + required this.country, + required this.flagPath, + }); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.grey[100], + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: const TextStyle(fontSize: 14, color: Colors.black54), + ), + const SizedBox(height: 4), + Text( + country, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + const SizedBox(width: 16), + ClipOval( + child: Container( + width: 50, + height: 50, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.transparent, + ), + child: Image.asset(flagPath, width: 50, height: 50, fit: BoxFit.cover), ), ), ], From f6c14eb2e55c44854edba0c33e746d3b6277d1c3 Mon Sep 17 00:00:00 2001 From: SurendarSuri30 Date: Thu, 12 Jun 2025 11:45:26 +0530 Subject: [PATCH 2/2] bhavin feedback changes --- .../Screens/charts/screens/chart_screen.dart | 8 +- .../Screens/charts/widgets/chart_widget.dart | 786 ++++++++++++++---- .../components/constant/constant.dart | 2 +- .../tab_routes/home_route.dart | 2 +- 4 files changed, 615 insertions(+), 183 deletions(-) diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index 19b5169c..379f1e93 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1462,6 +1462,10 @@ class _ChartScreen1State extends ConsumerState { void applyFilters(BuildContext context, List filters, List data, List dataCard, List selectedFilters) { + setState(() { + isLoading = true; + }); + Navigator.pop(context); print('applyFilters called'); print('Selected ApplyFilters: $selectedFilters'); @@ -1505,7 +1509,7 @@ class _ChartScreen1State extends ConsumerState { tabWiseKpi, // Ensure you are passing the correct KPI here formattedFilters // Pass the formatted filter data here ); - Navigator.pop(context); + // Navigator.pop(context); selectedFiltersStorage = List.from(selectedFilters); print('selectedFiltersStoraged- $selectedFiltersStorage'); @@ -1999,7 +2003,7 @@ class _ChartScreen1State extends ConsumerState { Navigator.pop(context); } else { setState(() { - isLoading = true; + // isLoading = true; chartsData = originalTabChartsData; cardData = originalTabCardData; }); diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index d8cd40b8..1e1cb772 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -90,20 +90,28 @@ class ChartWidget extends StatelessWidget { // Function to get colors for both English & Arabic keys List get uniqueColors { final Map translations = { - 'الاقتصاد': 'ECONOMY', - 'الاجتماعي': 'SOCIAL', - 'البيئة': 'ENVIRONMENT', + 'اقتصاد': 'ECONOMY', + 'اجتماعي': 'SOCIAL', + 'بيئة': 'ENVIRONMENT', }; + print('color check'); + print(translations); + print('chartHeader $chartHeader'); + print(translations[chartHeader]); + + String key = translations[chartHeader] ?? chartHeader; + print(key); + print(colorMap[key]); return colorMap[key] ?? [Colors.grey]; } List get uniqueColorsForTwo { final Map translations = { - 'الاقتصاد': 'ECONOMY', - 'الاجتماعي': 'SOCIAL', - 'البيئة': 'ENVIRONMENT', + 'اقتصاد': 'ECONOMY', + 'اجتماعي': 'SOCIAL', + 'بيئة': 'ENVIRONMENT', }; String key = translations[chartHeader] ?? chartHeader; @@ -112,9 +120,9 @@ class ChartWidget extends StatelessWidget { List get uniqueColorsForThree { final Map translations = { - 'الاقتصاد': 'ECONOMY', - 'الاجتماعي': 'SOCIAL', - 'البيئة': 'ENVIRONMENT', + 'اقتصاد': 'ECONOMY', + 'اجتماعي': 'SOCIAL', + 'بيئة': 'ENVIRONMENT', }; String key = translations[chartHeader] ?? chartHeader; @@ -1271,12 +1279,7 @@ class ChartWidget extends StatelessWidget { Set selectedYears = {1970, 1980, 1990, 2000, 2010, 2020}; Map groupColorMap = {}; int colorIndex = 0; - // for (String group in groupByValues) { - // // groupColorMap[group] = uniqueColors[colorIndex % uniqueColors.length]; - // groupColorMap[group] = uniqueColorsLine_trend_2[ - // colorIndex % uniqueColorsLine_trend_2.length]; - // colorIndex++; - // } + // Extract all years from the chart data List years = (chartData['response'] as List) @@ -1322,16 +1325,7 @@ class ChartWidget extends StatelessWidget { barColorsMap[key] = value.toString(); // Ensure values are strings }); bool hasBarColors = barColorsMap.isNotEmpty; - // var chartBarColorsRaw = chartData['chart_bar_color'] ?? {}; - // // Convert LinkedMap to Map - // Map chartBarColrs = - // Map.from(chartBarColorsRaw); - // // Now map to Color - // Map parsedChartBarColors = - // chartBarColrs.map((key, value) { - // return MapEntry(key, _hexToColor(value)); - // }); - // + List keys = chartBarColors['key'] ?? []; List colors = chartBarColors['color'] ?? []; @@ -1359,109 +1353,288 @@ class ChartWidget extends StatelessWidget { colorIndex++; } - // Generate line bars for the chart - List lineBars = lineBarsData( - filteredData, - groupByValues, - groupByKey, - parsedChartBarColors, - ); - return Column( - children: [ - Text( - chartData['chart_heading'] ?? '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 14, fontWeight: FontWeight.w400), - textAlign: TextAlign.center, - ), - SizedBox(height: 5), - Text( - chartData['chart_sub_heading'] ?? '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 13, fontWeight: FontWeight.w300), - textAlign: TextAlign.center, - ), - SizedBox(height: 10), - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Enable horizontal scrolling - padding: const EdgeInsets.only(right: 40, top: 10), - child: SizedBox( - width: (uniqueXValues.length * 50) + - 50, // Adjust width dynamically - child: LineChart( - LineChartData( - lineTouchData: lineTouchData1(context), - gridData: gridData(), - titlesData: titlesData1(uniqueXValues,context), - borderData: borderData(), - lineBarsData: lineBars, - minX: uniqueXValues.reduce((a, b) => a < b ? a : b), - maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), - ), - ), + + + final Map>> groupedData = {}; + +// Step 1: Group data by PLANT_TYPE + for (var item in filteredData) { + final plantType = item['ObsKey'][groupByKey]; + groupedData.putIfAbsent(plantType, () => []).add(item); + } + +// Step 2: Convert grouped data into List + final List lineBars = []; + final List colorPalette = [ + Color(0xFF6097CD), + Color(0xFFD086A7), + Color(0xFF98BCE5), + Color(0xFFA7B5C5), + Color(0xFFBED3EC), + Color(0xFFD4E3F4), + ]; + + String formatNumber(double value) { + if (value >= 1e12) { + return '${(value / 1e12).toStringAsFixed(2)}T'; + } else if (value >= 1e9) { + return '${(value / 1e9).toStringAsFixed(2)}B'; + } else if (value >= 1e6) { + return '${(value / 1e6).toStringAsFixed(2)}M'; + } else if (value >= 1e3) { + return '${(value / 1e3).toStringAsFixed(2)}K'; + } else { + return value.toStringAsFixed(2); // No decimals for small numbers + } + } + + final getXValue = chartData['chart_type_json']['x'] ?? ''; + groupedData.forEach((plantType, entries) { + final spots = entries.map((entry) { + final year = double.tryParse(entry['ObsKey'][getXValue].toString()) ?? 0; + final value = double.tryParse(entry['ObsValue']['Value'].toString()) ?? 0; + return FlSpot(year, value); + }).toList() + ..sort((a, b) => a.x.compareTo(b.x)); // Sort by year + final baseColor = groupColorMap[plantType] ?? Colors.grey; + lineBars.add( + LineChartBarData( + spots: spots, + isCurved: true, + barWidth: 3, + // color: groupColorMap[plantType] ?? Colors.grey, + color: baseColor.withOpacity(0.9), + dotData: FlDotData(show: true), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + // baseColor.withOpacity(0.2), // visible base color + // Colors.white, // fade to white + baseColor.withOpacity(0.4), // increase opacity + baseColor.withOpacity(0.0), // fade to transparent (not white) + ], + stops: [ + 0.2, // shift teal color start downward (20% from the top) + 1.0, // white at the bottom + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, ), ), + showingIndicators: List.generate(spots.length, (index) => index), + ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Wrap( - spacing: 12, - runSpacing: 8, - children: groupByValues.map((group) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 12, - height: 12, - color: groupColorMap[group], + ); + colorIndex++; + }); + + return Scaffold( + backgroundColor: Colors.white, + body: Padding( + padding: const EdgeInsets.all(10), + child: LayoutBuilder( + builder: (context, constraints) { + final chartWidth = constraints.maxWidth; + final chartHeight = constraints.maxHeight; + final allSpots = lineBars.expand((line) => line.spots); + final minY = allSpots.map((e) => e.y).reduce((a, b) => a < b ? a : b); + final maxY = allSpots.map((e) => e.y).reduce((a, b) => a > b ? a : b); + + + final xValues = allSpots.map((e) => e.x).toList(); + final minX = xValues.reduce((a, b) => a < b ? a : b).toInt(); + final maxX = xValues.reduce((a, b) => a > b ? a : b).toInt(); + + final paddingFactor = 0.3; // 10% extra padding + + final chartMinY = minY - (maxY - minY) * paddingFactor; + final chartMaxY = maxY + (maxY - minY) * paddingFactor; + + + return Column( + crossAxisAlignment: CrossAxisAlignment.center, // ensures center alignment + children: [ + Padding( + padding: const EdgeInsets.only(top: 0), + child: Text( + chartData['chart_heading'] ?? 'Production Quantity by Crop Type (Metric Tonne)', + style: TextStyle( + fontFamily: context.translate('Roboto', 'NotoKufi'), + fontSize: 14, + fontWeight: FontWeight.w400, + ), + textAlign: TextAlign.center, ), - SizedBox(width: 6), - Text(group, style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 14)), - ], - ); - }).toList(), - ), + ), + // SizedBox(height: 6), + Expanded( + child: Stack( + children: [ + LineChart( + LineChartData( + minY: chartMinY, + maxY: chartMaxY, + lineBarsData: lineBars, + clipData: FlClipData.all(), // make sure this doesn't clip the left side + + // Add space for tooltip/dot + // extraLeftTitlesReservedWidth: 24, + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.black, + fontSize: 10, + ); + + // Show only for full years + if (selectedYears.contains(value.toInt())) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Top tick mark (simulated using a container) + Container( + width: 1, + height: 8, + color: Colors.black, + margin: EdgeInsets.only(bottom: 2), + ), + Text(value.toInt().toString(), style: style), + ], + ); + } + return const SizedBox.shrink(); + }, + reservedSize: 30, + interval: 1, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + // interval: 5, + reservedSize: 90, + getTitlesWidget: (value, _) => + Text('${value.toInt()}', style: TextStyle(fontSize: 12)), + ), + ), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + borderData: FlBorderData( + show: true, + border: const Border( + left: BorderSide.none, + bottom: BorderSide(color: Colors.black), + ), + ), + gridData: FlGridData(show: false), + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + // tooltipBgColor: Colors.black.withOpacity(0.7), + fitInsideHorizontally: true, + fitInsideVertically: true, + getTooltipItems: (spots) { + return spots.map((spot) { + final x = spot.x.toInt(); + // if (x == minX || x == maxX) return null; + return LineTooltipItem( + formatNumber(spot.y), + const TextStyle(color: Colors.white), + ); + }).toList(); + }, + ), + ), + ), + ), + + ...lineBars.expand((barData) { + final List spots = barData.spots; + final color = barData.color ?? Colors.black; + + return spots.map((spot) { + final xPos = ((spot.x - minX) / (maxX - minX)) * chartWidth; + final yPos = (1 - (spot.y - chartMinY) / (chartMaxY - chartMinY)) * chartHeight; + // Prevent label from going outside on the left + double adjustedLeft = math.max(0, xPos - 30); + return Stack( + children: [ + Positioned( + left: adjustedLeft, // fine-tune horizontal position + top: yPos - 60, // fine-tune vertical position + child: Text( + formatNumber(spot.y), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 9, + fontWeight: FontWeight.w500, + // color: color, + color: Colors.black, + ), + ), + ) + ] + ); + + }); + }).toList(), + + ], + ), + ), + SizedBox(height: 12), + Wrap( // <-- Legend added here + 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, + fontFamily: context.translate('Roboto', 'NotoKufi'), + ), + ), + ], + ); + }).toList(), + ), + ], + ); + + + + }, ), - // Chart - ], + ), ); case 'line_trend_2': - // final List uniqueColorsLine_trend_2 = [ - // Color(0xFF6097CD), - // Color(0xFFD086A7), - // Color(0xFF98BCE5), - // Color(0xFFA7B5C5), - // Color(0xFFBED3EC), - // Color(0xFFD4E3F4), - // ]; + final List uniqueColorsLine_trend_2 = [ + Color(0xFF6097CD), + Color(0xFFD086A7), + ]; Set selectedYears = {1970, 1980, 1990, 2000, 2010, 2020}; Map groupColorMap = {}; int colorIndex = 0; - // for (String group in groupByValues) { - // // groupColorMap[group] = uniqueColorsLine_trend_2[ - // // colorIndex % uniqueColorsLine_trend_2.length]; - // groupColorMap[group] = uniqueColors[colorIndex % uniqueColors.length]; - // // groupColorMap[group] = adjustColorlineTrend(bodyColor, colorIndex); - // colorIndex++; - // } + // Extract all years from the chart data List years = (chartData['response'] as List) .map( (entry) => - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, - ) + int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, + ) .toList(); if (years.isEmpty) { @@ -1482,7 +1655,7 @@ class ChartWidget extends StatelessWidget { // Filter chart data to include only the selected years List filteredData = - (chartData['response'] as List).where((entry) { + (chartData['response'] as List).where((entry) { int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; return selectedYears.contains(year); }).toList(); @@ -1490,91 +1663,344 @@ class ChartWidget extends StatelessWidget { Set uniqueXValues = filteredData .map( (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), - ) + ) .toSet(); - print('uniqueXValuesLineTrend2- $uniqueXValues'); - var chartBarColors = chartData['chart_bar_color'] ?? {}; Map barColorsMap = {}; + chartBarColors.forEach((key, value) { barColorsMap[key] = value.toString(); // Ensure values are strings }); bool hasBarColors = barColorsMap.isNotEmpty; - var chartBarColorsRaw = chartData['chart_bar_color'] ?? {}; - // Convert LinkedMap to Map - Map chartBarColrs = Map.from( - chartBarColorsRaw, - ); + List keys = chartBarColors['key'] ?? []; + List colors = chartBarColors['color'] ?? []; - // Now map to Color - Map parsedChartBarColors = chartBarColrs.map(( - key, - value, - ) { - return MapEntry(key, _hexToColor(value)); - }); + print('RT1keys - $keys'); + print('RT1colors - $colors'); + + // Convert to a map for easy lookup + Map parsedChartBarColors = {}; + for (int i = 0; i < keys.length; i++) { + parsedChartBarColors[keys[i].toString()] = _hexToColor( + colors[i].toString(), + ); + } + print('RTLinr1 - $parsedChartBarColors'); for (String group in groupByValues) { if (parsedChartBarColors.containsKey(group)) { groupColorMap[group] = - parsedChartBarColors[group]!; // Directly assign as Color + parsedChartBarColors[group]!; // Directly assign as Color } else { groupColorMap[group] = - uniqueColors[colorIndex % uniqueColors.length]; + uniqueColors[colorIndex % uniqueColors.length]; } colorIndex++; } - // Generate line bars for the chart - List lineBars = lineBarsData2(filteredData); - return Column( - children: [ - Text( - chartData['chart_heading'] ?? '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 14, fontWeight: FontWeight.w400), - textAlign: TextAlign.center, - ), - SizedBox(height: 5), - Text( - '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 13, fontWeight: FontWeight.w300), - textAlign: TextAlign.center, - ), - SizedBox(height: 10), - // Chart - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Enable horizontal scrolling - padding: const EdgeInsets.only(right: 40, top: 20), - child: SizedBox( - width: (uniqueXValues.length * 50) + - 50, // Adjust width dynamically - child: LineChart( - LineChartData( - lineTouchData: lineTouchData1(context), - gridData: gridData(), - titlesData: titlesData1(uniqueXValues,context), - borderData: borderData(), - lineBarsData: lineBars, - minX: uniqueXValues.reduce((a, b) => a < b ? a : b), - maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), - minY: 0, - ), - ), + + + + final Map>> groupedData = {}; + +// Step 1: Group data by PLANT_TYPE + for (var item in filteredData) { + final plantType = item['ObsKey'][groupByKey]; + groupedData.putIfAbsent(plantType, () => []).add(item); + } + +// Step 2: Convert grouped data into List + final List lineBars = []; + final List colorPalette = [ + Color(0xFF6097CD), + Color(0xFFD086A7), + Color(0xFF98BCE5), + Color(0xFFA7B5C5), + Color(0xFFBED3EC), + Color(0xFFD4E3F4), + ]; + + String formatNumber(double value) { + if (value >= 1e12) { + return '${(value / 1e12).toStringAsFixed(2)}T'; + } else if (value >= 1e9) { + return '${(value / 1e9).toStringAsFixed(2)}B'; + } else if (value >= 1e6) { + return '${(value / 1e6).toStringAsFixed(2)}M'; + } else if (value >= 1e3) { + return '${(value / 1e3).toStringAsFixed(2)}K'; + } else { + return value.toStringAsFixed(2); // No decimals for small numbers + } + } + + final getXValue = chartData['chart_type_json']['x'] ?? ''; + groupedData.forEach((plantType, entries) { + // Create a map to store population values by year and gender + Map> yearGenderMap = {}; + + for (var entry in filteredData) { + int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'].toString()) ?? 0; + String gender = entry['ObsKey']['GENDER']; + + double value = + double.tryParse(entry['ObsValue']['Value'].toString()) ?? 0.0; + + if (!yearGenderMap.containsKey(year)) { + yearGenderMap[year] = {'M': 0.0, 'F': 0.0}; + } + + if (gender == 'Male' || gender == 'ذكر') { + yearGenderMap[year]!['M'] = value; + } else if (gender == 'Female' || gender == 'أنثى') { + yearGenderMap[year]!['F'] = value; + } + } + + // Calculate the ratio (M/F) * 100 for each year + List spots = []; + yearGenderMap.forEach((year, genderMap) { + if (genderMap['M'] != 0.0 && genderMap['F'] != 0.0) { + double ratio = (genderMap['M']! / genderMap['F']!) * 100; + spots.add(FlSpot(year.toDouble(), ratio)); + } + }); + final baseColor = groupColorMap[plantType] ?? Colors.grey; + + lineBars.add( + LineChartBarData( + spots: spots, + isCurved: true, + barWidth: 3, + // color: groupColorMap[plantType] ?? Colors.grey, + color: baseColor.withOpacity(0.9), + dotData: FlDotData(show: true), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + // baseColor.withOpacity(0.2), // visible base color + // Colors.white, // fade to white + baseColor.withOpacity(0.4), // increase opacity + baseColor.withOpacity(0.0), // fade to transparent (not white) + ], + stops: [ + 0.2, // shift teal color start downward (20% from the top) + 1.0, // white at the bottom + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, ), ), + showingIndicators: List.generate(spots.length, (index) => index), + ), - ], + ); + colorIndex++; + }); + + return Scaffold( + backgroundColor: Colors.white, + body: Padding( + padding: const EdgeInsets.all(10), + child: LayoutBuilder( + builder: (context, constraints) { + final chartWidth = constraints.maxWidth; + final chartHeight = constraints.maxHeight; + final allSpots = lineBars.expand((line) => line.spots); + final minY = allSpots.map((e) => e.y).reduce((a, b) => a < b ? a : b); + final maxY = allSpots.map((e) => e.y).reduce((a, b) => a > b ? a : b); + + + final xValues = allSpots.map((e) => e.x).toList(); + final minX = xValues.reduce((a, b) => a < b ? a : b).toInt(); + final maxX = xValues.reduce((a, b) => a > b ? a : b).toInt(); + + final paddingFactor = 0.3; // 10% extra padding + + final chartMinY = minY - (maxY - minY) * paddingFactor; + final chartMaxY = maxY + (maxY - minY) * paddingFactor; + + + return Column( + crossAxisAlignment: CrossAxisAlignment.center, // ensures center alignment + children: [ + Padding( + padding: const EdgeInsets.only(top: 0), + child: Text( + chartData['chart_heading'] ?? 'Production Quantity by Crop Type (Metric Tonne)', + style: TextStyle( + fontFamily: context.translate('Roboto', 'NotoKufi'), + fontSize: 14, + fontWeight: FontWeight.w400, + ), + textAlign: TextAlign.center, + ), + ), + // SizedBox(height: 6), + Expanded( + child: Stack( + children: [ + LineChart( + LineChartData( + minY: chartMinY, + maxY: chartMaxY, + lineBarsData: lineBars, + clipData: FlClipData.all(), // make sure this doesn't clip the left side + + // Add space for tooltip/dot + // extraLeftTitlesReservedWidth: 24, + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.black, + fontSize: 10, + ); + + // Show only for full years + if (selectedYears.contains(value.toInt())) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Top tick mark (simulated using a container) + Container( + width: 1, + height: 8, + color: Colors.black, + margin: EdgeInsets.only(bottom: 2), + ), + Text(value.toInt().toString(), style: style), + ], + ); + } + return const SizedBox.shrink(); + }, + reservedSize: 30, + interval: 1, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + // interval: 5, + reservedSize: 90, + getTitlesWidget: (value, _) => + Text('${value.toInt()}', style: TextStyle(fontSize: 12)), + ), + ), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + borderData: FlBorderData( + show: true, + border: const Border( + left: BorderSide.none, + bottom: BorderSide(color: Colors.black), + ), + ), + gridData: FlGridData(show: false), + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + // tooltipBgColor: Colors.black.withOpacity(0.7), + fitInsideHorizontally: true, + fitInsideVertically: true, + getTooltipItems: (spots) { + return spots.map((spot) { + final x = spot.x.toInt(); + // if (x == minX || x == maxX) return null; + // Use barIndex to determine which line this belongs to + final barIndex = spot.barIndex; + if (lineBars[barIndex].spots.isEmpty) return null; + + // Check the group name (plantType) from your groupedData order + final plantType = groupedData.keys.toList()[barIndex]; + print('plantType $plantType'); + + if (plantType != "Male" && plantType != "ذكر") { + return null; + } + return LineTooltipItem( + formatNumber(spot.y), + const TextStyle(color: Colors.white), + ); + }).toList(); + }, + ), + ), + ), + ), + + ...lineBars.expand((barData) { + final List spots = barData.spots; + final color = barData.color ?? Colors.black; + + return spots.map((spot) { + final xPos = ((spot.x - minX) / (maxX - minX)) * chartWidth; + final yPos = (1 - (spot.y - chartMinY) / (chartMaxY - chartMinY)) * chartHeight; + // Prevent label from going outside on the left + double adjustedLeft = math.max(0, xPos - 30); + return Stack( + children: [ + Positioned( + left: adjustedLeft, // fine-tune horizontal position + top: yPos - 70, // fine-tune vertical position + child: Text( + formatNumber(spot.y), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 9, + fontWeight: FontWeight.w500, + // color: color, + color: Colors.black, + ), + ), + ) + ] + ); + + }); + }).toList(), + + ], + ), + ), + SizedBox(height: 12), + // Wrap( // <-- Legend added here + // 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, + // fontFamily: context.translate('Roboto', 'NotoKufi'), + // ), + // ), + // ], + // ); + // }).toList(), + // ), + ], + ); + + + + }, + ), + ), ); case 'bar_chart': // Extract groupBy values and their corresponding y-axis values @@ -1720,7 +2146,7 @@ class ChartWidget extends StatelessWidget { child: Center( child: SizedBox( width: xAxisData.length * - (40 + 10), // Bar width + manual spacing + (80 + 10), // Bar width + manual spacing child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, @@ -1844,15 +2270,15 @@ class ChartWidget extends StatelessWidget { return Padding( padding: const EdgeInsets.only( - top: 8.0, - left: 75.0, + top: 0, + left: 0, ), child: SizedBox( width: 100, // Limit width to force wrapping child: Transform.rotate( // angle: -0.5, - angle: -1.5, + angle: 0, child: TooltipTheme( data: TooltipThemeData( @@ -1878,7 +2304,7 @@ class ChartWidget extends StatelessWidget { // title, displayTitle, softWrap: true, - textAlign: TextAlign.right, + textAlign: TextAlign.center, style: TextStyle(fontFamily: context.translate( 'Roboto', 'NotoKufi', @@ -1896,7 +2322,7 @@ class ChartWidget extends StatelessWidget { } return Container(); }, - reservedSize: 110, + reservedSize: 50, ), ), topTitles: AxisTitles( @@ -1931,7 +2357,7 @@ class ChartWidget extends StatelessWidget { toY: value == 0 ? 0.1 : value, color: bodyColor, borderRadius: BorderRadius.circular(4), - width: 20, + width: 35, ), ], showingTooltipIndicators: [0], @@ -2219,6 +2645,7 @@ class ChartWidget extends StatelessWidget { ) { return MapEntry(key, _hexToColor(value)); }); + print('parsedChartBarColors1100 $parsedChartBarColors'); if (kDebugMode) { print('Converted barColorsMap: $barColorsMap'); @@ -4368,6 +4795,7 @@ class ChartWidget extends StatelessWidget { colorIndex % 2]; // Alternate between two colors colorIndex++; // Update index for next bar } else { + print('check fl chart'); // barColor = chartBarColors[gender] ?? Colors.grey; // Default gender-based color barColor = chartBarColors[normalizedGender] ?? Colors.grey; } diff --git a/lib/presentation/components/constant/constant.dart b/lib/presentation/components/constant/constant.dart index b5422547..6fbc00ab 100644 --- a/lib/presentation/components/constant/constant.dart +++ b/lib/presentation/components/constant/constant.dart @@ -16,4 +16,4 @@ TextStyle subtitleStyle(BuildContext context) { TextStyle robotoRegular11(BuildContext context) {return TextStyle(fontFamily: context.translate('Roboto', 'NotoKufi'), fontWeight: FontWeight.w400, - fontSize: 11 * 1.1,color: Color(0xFF000000),);} + fontSize: 12 * 1.1,color: Color(0xFF000000),);} diff --git a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart index 245038d0..f9332ee8 100644 --- a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart +++ b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart @@ -1571,7 +1571,7 @@ class InfoCard extends StatelessWidget { Text( title, style: TextStyle( - fontSize: 11, + fontSize: 13, fontWeight: FontWeight.w400, letterSpacing: 0, // color: Colors.black,