From cfe5b5bf20b8bb8880f7c8acb24fda7d64a3e6fd Mon Sep 17 00:00:00 2001 From: venbaittech Date: Tue, 25 Feb 2025 18:08:20 +0530 Subject: [PATCH] bookmark and cards changes done --- android/app/build.gradle | 4 +- lib/l10n/intl_ar.arb | 5 + lib/l10n/intl_en.arb | 8 +- .../Screens/charts/screens/chart_screen.dart | 1405 +++++++++++------ .../Screens/charts/widgets/chart_widget.dart | 71 +- .../drawer_routes/Drawer Items/bookmark.dart | 32 +- pubspec.yaml | 2 +- 7 files changed, 1002 insertions(+), 525 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 1ca707ed..a74f4048 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) { def flutterVersionCode = localProperties.getProperty("flutter.versionCode") if (flutterVersionCode == null) { - flutterVersionCode = "26" + flutterVersionCode = "27" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.25" + flutterVersionName = "1.0.26" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index c272b10e..83622a31 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -1,4 +1,9 @@ { + "all_bookmarks":"كل العلامات المرجعية", + "economy_title":" الاقتصاد", + "social_title":"اجتماعي", + "environment_title":"البيئة", + "bookmarks": "الإشارات المرجعية", "feedback_title": "تعليق", "feedback_failed_msg": "لم يتم إرسال تعليقاتك. يرجى المحاولة مرة أخرى.", "thankYou": "شكراً", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 8f5fba5a..90c050e0 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,7 +1,11 @@ { - -"feedback_title": "Feedback", + "all_bookmarks":"All Bookmarks", + "economy_title":"Economy", + "social_title":"Social", + "environment_title":"Environment", + "bookmarks": "Bookmarks", + "feedback_title": "Feedback", "feedback_failed_msg": "Your feedback could not be \n submitted. Please try again", "thankYou": "Thank you", "feedback_message": "For your valuable feedback, we truly appreciate your input!", diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index 8f73b70f..dacfc19f 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -2125,25 +2125,29 @@ class _ChartScreen1State extends ConsumerState { SizedBox(width: 10), Row( children: [ - Text( - context.translate( - 'Share', - 'يشارك', - ), - style: const TextStyle( - fontSize: 16, - color: Colors.white, - ), - ), - SizedBox(width: 5), GestureDetector( onTap: () => shareCurrentPage(context), - child: SvgPicture.asset( + + child: Row( + children: [ + Text( + context.translate( + 'Share', + 'يشارك', + ), + style: const TextStyle( + fontSize: 16, + color: Colors.white, + ), + ), + SizedBox(width: 5), + SvgPicture.asset( UaeNumbersAssetPath.share, semanticsLabel: 'share', width: 24, height: 24, - )), + ) + ],),), ], ), SizedBox( @@ -2253,481 +2257,528 @@ class _ChartScreen1State extends ConsumerState { // ), // nonChartData Cards Padding( - padding: const EdgeInsets.all(3.34), - child: GridView.builder( - key: cardKey, - itemCount: cardData.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - // crossAxisCount: cardData.length % 2 == 0 ? 2 : 3, + padding: const EdgeInsets.all(8.0), + child: LayoutBuilder( + builder: (context, constraints) { + List rows = []; + List tempRow = []; - crossAxisSpacing: 2, - - mainAxisSpacing: 5, - - childAspectRatio: MediaQuery.of(context) - .size - .width / - (MediaQuery.of(context).size.height / - (cardData.length % 2 == 0 ? 2 : 2)), - ), - - // Sort and filter the cardData - - itemBuilder: (context, index) { - final item = cardData[index]; - print('item item item $item'); - final chart_type = item['chart_type']; - final chart_heading = item['chart_heading']; - final card_full_length = - item['card_full_length']; - print('cardfulllength $card_full_length'); - final response = - item['response'] as List? ?? - []; - final card_logo = item['card_logo']; - final data = - apiService.processNonChartData(item); - print('processNonChartData'); - - double cardHeight = - (chart_type == 'totals' || - chart_type == 'averages') - ? 180.0 - : 130.0; - // double myheight = MediaQuery.of(context).size.height; - // double mywidth = MediaQuery.of(context).size.width; - // final cardWidth = rowItems.length == 1 ? myWidth : (myWidth - 16) / 2.6; - print('find width $cardData'); - final itemdata = cardData[index]; - // bool isOddLength = cardData.length % 2 != 0; - // bool isLastSingleCard = isOddLength && - // index == cardData.length - 1; - // print('isLastSingleCard $isLastSingleCard'); - - if (response.isEmpty) { - return const SizedBox.shrink(); - // return Container( - // color: Colors.redAccent, - // ); + for (var card in cardData) { + if (card['card_full_length'] == true) { + if (tempRow.isNotEmpty) { + rows.add(Row(children: tempRow)); + tempRow = []; + } + rows.add(Row( + children: [ + Expanded( + child: CardWidget( + card: card, + chartScreenData: + chartScreenData)), + ], + )); + } else { + tempRow.add(Expanded( + child: CardWidget( + card: card, + chartScreenData: + chartScreenData))); + if (tempRow.length == 2) { + rows.add(Row(children: tempRow)); + tempRow = []; + } + } } - if (response.length == 1) { - return Container( - margin: const EdgeInsets.all(10), - width: card_full_length - ? double.infinity - : null, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(12), - border: Border.all( - color: Color(int.parse( - (chartScreenData[ - 'border_color'] ?? - '#898C81') - .replaceFirst( - '#', '0xff'))), - // Dynamic border color - width: - 1, // Adjust border thickness - ), - ), - child: Card( - margin: const EdgeInsets.all(0), - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(12), - ), - elevation: 2, - child: Container( - height: cardHeight, - padding: const EdgeInsets.only( - left: 16.0, - right: 16.0, - bottom: 1.0, - top: 1.0), - decoration: BoxDecoration( - color: Colors - .white, // Move color inside BoxDecoration - borderRadius: BorderRadius.circular( - 12), // Ensure border radius is applied - ), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Image.network( - card_logo ?? '', - width: 30, - height: 30, - errorBuilder: (context, - error, stackTrace) { - return Icon(Icons.public, - color: - Color(0xFF90B0D5), - size: - 30); // Fallback icon - }, - ), - const SizedBox(height: 1), - MouseRegion( - onEnter: (event) { - // Show tooltip on hover - final overlay = Overlay - .of(context) - .context - .findRenderObject() - as RenderBox; - final entry = - OverlayEntry( - builder: (context) => - Positioned( - left: overlay - .localToGlobal( - Offset.zero) - .dx, - top: overlay - .localToGlobal( - Offset.zero) - .dy, - child: Material( - color: Colors - .transparent, - child: Container( - padding: - EdgeInsets - .all(8), - decoration: - BoxDecoration( - color: Colors - .black87, - borderRadius: - BorderRadius - .circular( - 4), - ), - child: Text( - chart_heading ?? - 'NA', - style: TextStyle( - color: Colors - .white), - ), - ), - ), - ), - ); - Overlay.of(context) - .insert(entry); - Future.delayed( - Duration(seconds: 2), - () => entry.remove()); - }, - child: Text( - chart_heading ?? 'NA', - textAlign: - TextAlign.center, - maxLines: 2, - overflow: TextOverflow - .ellipsis, // Truncate text with '...' - style: TextStyle( - fontSize: 11, - fontWeight: - FontWeight.w400, - color: Colors.black87, - ), - ), - ), - const SizedBox(height: 5), - Text( - RegExp(r'\d').hasMatch( - response[0][ - 'display_value'] ?? - '') - ? '(${response[0]['display_value'] ?? 'NA'})' - : '${response[0]['display_value'] ?? 'NA'}', - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: TextOverflow - .ellipsis, // Truncate if text overflows - ), - maxLines: - 1, // Limit to one line to prevent overflow - textAlign: TextAlign - .center, // Ensure proper alignment - ), - const SizedBox(height: 1), - Row( - mainAxisAlignment: - MainAxisAlignment - .center, // Center-aligns the row contents - children: [ - Text( - response[0]['value'] ?? - 'NA', - textAlign: TextAlign - .center, // Ensures text is centered - style: TextStyle( - fontSize: 23, - fontWeight: - FontWeight.w800, - color: (response[0][ - 'font_color'] ?? - '') - .isEmpty - ? bodyColor - : _getColorFromHex( - response[0][ - 'font_color']), - ), - ), - const SizedBox( - width: - 4), // Space between text and icon - if (response[0] - ['calculation'] == - 'different') ...[ - if (response[0][ - 'font_color'] == - '#D83731') - const Icon( - Icons - .arrow_downward, - color: Colors.red, - size: 20) - else if (response[0][ - 'font_color'] == - '#11AF22') - const Icon( - Icons - .arrow_upward, - color: - Colors.green, - size: 20), - ], - ], - ) - ], - ), - ), - )); - } else { - return Container( - margin: const EdgeInsets.all(10), - width: card_full_length - ? double.infinity - : null, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(12), - border: Border.all( - color: Color(int.parse((chartScreenData[ - 'border_color'] ?? - '#898C81') - .replaceFirst('#', - '0xff'))), // Dynamic border color - width: 1, // Adjust border thickness - ), - ), - child: Card( - margin: const EdgeInsets.all(0), - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(12), - ), - elevation: - 0, // Remove shadow to keep only the outli - child: Container( - height: cardHeight, - padding: const EdgeInsets.all(10.0), - decoration: BoxDecoration( - color: Colors - .white, // Move color inside BoxDecoration - borderRadius: BorderRadius.circular( - 12), // Ensure border radius is applied - ), - child: Column( - mainAxisSize: MainAxisSize - .min, // Adjust card height based on content - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - // const Icon(Icons.public, - // color: Color(0xFF90B0D5), size: 30), - Image.network( - card_logo ?? '', - width: 30, - height: 30, - errorBuilder: (context, error, - stackTrace) { - return Icon(Icons.public, - color: - Color(0xFF90B0D5), - size: - 30); // Fallback icon - }, - ), - const SizedBox(height: 3), - MouseRegion( - onEnter: (event) { - final overlay = - Overlay.of(context); - final entry = OverlayEntry( - builder: (context) => - Positioned( - left: event.position.dx, - top: event.position.dy + - 10, // Adjust tooltip position - child: Material( - color: Colors - .transparent, - child: Container( - padding: - EdgeInsets.all( - 8), - decoration: - BoxDecoration( - color: Colors - .black87, - borderRadius: - BorderRadius - .circular( - 4), - ), - child: Text( - chart_heading ?? - 'NA', - style: TextStyle( - color: Colors - .white, - fontSize: 10), - ), - ), - ), - ), - ); - overlay.insert(entry); - Future.delayed( - Duration(seconds: 2), - () => entry.remove()); - }, - child: SizedBox( - width: double - .infinity, // Ensures it uses available space - child: Text( - chart_heading ?? 'NA', - textAlign: - TextAlign.center, - maxLines: 2, - overflow: TextOverflow - .ellipsis, // Truncate with '...' - style: TextStyle( - fontSize: 11, - fontWeight: - FontWeight.w400, - color: Colors.black87, - ), - ), - ), - ), - const SizedBox(height: 1), - Text( - // '(${response[0]['display_value'] ?? 'NA'})', - - RegExp(r'\d').hasMatch(response[ - 0][ - 'display_value'] ?? - '') - ? '(${response[0]['display_value'] ?? 'NA'})' - : '${response[0]['display_value'] ?? 'NA'}', - - style: const TextStyle( - fontSize: 11, - color: Colors.grey, - overflow: - TextOverflow.ellipsis, - ), - ), - const SizedBox(height: 1), - Text( - response[0]['value'] ?? 'NA', - overflow: TextOverflow - .ellipsis, // Truncate text if it overflows - maxLines: - 1, // Ensures text stays in a single line - style: TextStyle( - fontSize: 23, - fontWeight: FontWeight.w900, - color: (response[0][ - 'font_color'] ?? - '') - .isEmpty - ? bodyColor - : _getColorFromHex( - response[0] - ['font_color']), - ), - ), - SizedBox( - height: - 2, // Height of the divider - child: Divider( - color: Color(0xFFBBBCBD), - thickness: - 1, // Divider line thickness - ), - ), - Text( - response[1]['value'] ?? 'NA', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: (response[1][ - 'font_color'] ?? - '') - .isEmpty - ? const Color( - 0xFFD83731) - : _getColorFromHex( - response[1] - ['font_color']), - ), - textAlign: TextAlign - .center, // Ensure proper alignment - overflow: TextOverflow - .ellipsis, // Truncate if text overflows - ), - Text( - // '(${response[1]['display_value'] ?? 'NA'})', - RegExp(r'\d').hasMatch(response[ - 1][ - 'display_value'] ?? - '') - ? '(${response[1]['display_value'] ?? 'NA'})' - : '${response[1]['display_value'] ?? 'NA'}', - style: const TextStyle( - fontSize: 8, - fontWeight: FontWeight.w500, - color: Colors.grey, - overflow: - TextOverflow.ellipsis, - ), - ), - ], - ), - ), - ), - ); + if (tempRow.isNotEmpty) { + rows.add(Row(children: tempRow)); } + + return SingleChildScrollView( + child: Column( + children: rows, + ), + ); }, ), ), + // Padding( + // padding: const EdgeInsets.all(3.34), + // child: GridView.builder( + // key: cardKey, + // itemCount: cardData.length, + // shrinkWrap: true, + // physics: const NeverScrollableScrollPhysics(), + // gridDelegate: + // SliverGridDelegateWithFixedCrossAxisCount( + // crossAxisCount: 2, + // // crossAxisCount: cardData.length % 2 == 0 ? 2 : 3, + // + // crossAxisSpacing: 2, + // + // mainAxisSpacing: 5, + // + // childAspectRatio: MediaQuery.of(context) + // .size + // .width / + // (MediaQuery.of(context).size.height / + // (cardData.length % 2 == 0 ? 2 : 2)), + // ), + // + // // Sort and filter the cardData + // + // itemBuilder: (context, index) { + // final item = cardData[index]; + // print('item item item $item'); + // final chart_type = item['chart_type']; + // final chart_heading = item['chart_heading']; + // final card_full_length = + // item['card_full_length']; + // print('cardfulllength $card_full_length'); + // final response = + // item['response'] as List? ?? + // []; + // final card_logo = item['card_logo']; + // final data = + // apiService.processNonChartData(item); + // print('processNonChartData'); + // + // double cardHeight = + // (chart_type == 'totals' || + // chart_type == 'averages') + // ? 180.0 + // : 130.0; + // // double myheight = MediaQuery.of(context).size.height; + // // double mywidth = MediaQuery.of(context).size.width; + // // final cardWidth = rowItems.length == 1 ? myWidth : (myWidth - 16) / 2.6; + // print('find width $cardData'); + // final itemdata = cardData[index]; + // // bool isOddLength = cardData.length % 2 != 0; + // // bool isLastSingleCard = isOddLength && + // // index == cardData.length - 1; + // // print('isLastSingleCard $isLastSingleCard'); + // + // if (response.isEmpty) { + // return const SizedBox.shrink(); + // // return Container( + // // color: Colors.redAccent, + // // ); + // } + // if (response.length == 1) { + // return Container( + // margin: const EdgeInsets.all(10), + // width: card_full_length + // ? double.infinity + // : null, + // decoration: BoxDecoration( + // borderRadius: + // BorderRadius.circular(12), + // border: Border.all( + // color: Color(int.parse( + // (chartScreenData[ + // 'border_color'] ?? + // '#898C81') + // .replaceFirst( + // '#', '0xff'))), + // // Dynamic border color + // width: + // 1, // Adjust border thickness + // ), + // ), + // child: Card( + // margin: const EdgeInsets.all(0), + // shape: RoundedRectangleBorder( + // borderRadius: + // BorderRadius.circular(12), + // ), + // elevation: 2, + // child: Container( + // height: cardHeight, + // padding: const EdgeInsets.only( + // left: 16.0, + // right: 16.0, + // bottom: 1.0, + // top: 1.0), + // decoration: BoxDecoration( + // color: Colors + // .white, // Move color inside BoxDecoration + // borderRadius: BorderRadius.circular( + // 12), // Ensure border radius is applied + // ), + // child: Column( + // mainAxisSize: MainAxisSize.min, + // mainAxisAlignment: + // MainAxisAlignment.center, + // children: [ + // Image.network( + // card_logo ?? '', + // width: 30, + // height: 30, + // errorBuilder: (context, + // error, stackTrace) { + // return Icon(Icons.public, + // color: + // Color(0xFF90B0D5), + // size: + // 30); // Fallback icon + // }, + // ), + // const SizedBox(height: 1), + // MouseRegion( + // onEnter: (event) { + // // Show tooltip on hover + // final overlay = Overlay + // .of(context) + // .context + // .findRenderObject() + // as RenderBox; + // final entry = + // OverlayEntry( + // builder: (context) => + // Positioned( + // left: overlay + // .localToGlobal( + // Offset.zero) + // .dx, + // top: overlay + // .localToGlobal( + // Offset.zero) + // .dy, + // child: Material( + // color: Colors + // .transparent, + // child: Container( + // padding: + // EdgeInsets + // .all(8), + // decoration: + // BoxDecoration( + // color: Colors + // .black87, + // borderRadius: + // BorderRadius + // .circular( + // 4), + // ), + // child: Text( + // chart_heading ?? + // 'NA', + // style: TextStyle( + // color: Colors + // .white), + // ), + // ), + // ), + // ), + // ); + // Overlay.of(context) + // .insert(entry); + // Future.delayed( + // Duration(seconds: 2), + // () => entry.remove()); + // }, + // child: Text( + // chart_heading ?? 'NA', + // textAlign: + // TextAlign.center, + // maxLines: 2, + // overflow: TextOverflow + // .ellipsis, // Truncate text with '...' + // style: TextStyle( + // fontSize: 11, + // fontWeight: + // FontWeight.w400, + // color: Colors.black87, + // ), + // ), + // ), + // const SizedBox(height: 5), + // Text( + // RegExp(r'\d').hasMatch( + // response[0][ + // 'display_value'] ?? + // '') + // ? '(${response[0]['display_value'] ?? 'NA'})' + // : '${response[0]['display_value'] ?? 'NA'}', + // style: const TextStyle( + // fontSize: 11, + // color: Colors.grey, + // overflow: TextOverflow + // .ellipsis, // Truncate if text overflows + // ), + // maxLines: + // 1, // Limit to one line to prevent overflow + // textAlign: TextAlign + // .center, // Ensure proper alignment + // ), + // const SizedBox(height: 1), + // Row( + // mainAxisAlignment: + // MainAxisAlignment + // .center, // Center-aligns the row contents + // children: [ + // Text( + // response[0]['value'] ?? + // 'NA', + // textAlign: TextAlign + // .center, // Ensures text is centered + // style: TextStyle( + // fontSize: 23, + // fontWeight: + // FontWeight.w800, + // color: (response[0][ + // 'font_color'] ?? + // '') + // .isEmpty + // ? bodyColor + // : _getColorFromHex( + // response[0][ + // 'font_color']), + // ), + // ), + // const SizedBox( + // width: + // 4), // Space between text and icon + // if (response[0] + // ['calculation'] == + // 'different') ...[ + // if (response[0][ + // 'font_color'] == + // '#D83731') + // const Icon( + // Icons + // .arrow_downward, + // color: Colors.red, + // size: 20) + // else if (response[0][ + // 'font_color'] == + // '#11AF22') + // const Icon( + // Icons + // .arrow_upward, + // color: + // Colors.green, + // size: 20), + // ], + // ], + // ) + // ], + // ), + // ), + // )); + // } else { + // return Container( + // margin: const EdgeInsets.all(10), + // width: card_full_length + // ? double.infinity + // : null, + // decoration: BoxDecoration( + // borderRadius: + // BorderRadius.circular(12), + // border: Border.all( + // color: Color(int.parse((chartScreenData[ + // 'border_color'] ?? + // '#898C81') + // .replaceFirst('#', + // '0xff'))), // Dynamic border color + // width: 1, // Adjust border thickness + // ), + // ), + // child: Card( + // margin: const EdgeInsets.all(0), + // shape: RoundedRectangleBorder( + // borderRadius: + // BorderRadius.circular(12), + // ), + // elevation: + // 0, // Remove shadow to keep only the outli + // + // child: Container( + // height: cardHeight, + // padding: const EdgeInsets.all(10.0), + // decoration: BoxDecoration( + // color: Colors + // .white, // Move color inside BoxDecoration + // borderRadius: BorderRadius.circular( + // 12), // Ensure border radius is applied + // ), + // child: Column( + // mainAxisSize: MainAxisSize + // .min, // Adjust card height based on content + // mainAxisAlignment: + // MainAxisAlignment.center, + // children: [ + // // const Icon(Icons.public, + // // color: Color(0xFF90B0D5), size: 30), + // Image.network( + // card_logo ?? '', + // width: 30, + // height: 30, + // errorBuilder: (context, error, + // stackTrace) { + // return Icon(Icons.public, + // color: + // Color(0xFF90B0D5), + // size: + // 30); // Fallback icon + // }, + // ), + // const SizedBox(height: 3), + // MouseRegion( + // onEnter: (event) { + // final overlay = + // Overlay.of(context); + // final entry = OverlayEntry( + // builder: (context) => + // Positioned( + // left: event.position.dx, + // top: event.position.dy + + // 10, // Adjust tooltip position + // child: Material( + // color: Colors + // .transparent, + // child: Container( + // padding: + // EdgeInsets.all( + // 8), + // decoration: + // BoxDecoration( + // color: Colors + // .black87, + // borderRadius: + // BorderRadius + // .circular( + // 4), + // ), + // child: Text( + // chart_heading ?? + // 'NA', + // style: TextStyle( + // color: Colors + // .white, + // fontSize: 10), + // ), + // ), + // ), + // ), + // ); + // overlay.insert(entry); + // Future.delayed( + // Duration(seconds: 2), + // () => entry.remove()); + // }, + // child: SizedBox( + // width: double + // .infinity, // Ensures it uses available space + // child: Text( + // chart_heading ?? 'NA', + // textAlign: + // TextAlign.center, + // maxLines: 2, + // overflow: TextOverflow + // .ellipsis, // Truncate with '...' + // style: TextStyle( + // fontSize: 11, + // fontWeight: + // FontWeight.w400, + // color: Colors.black87, + // ), + // ), + // ), + // ), + // const SizedBox(height: 1), + // Text( + // // '(${response[0]['display_value'] ?? 'NA'})', + // + // RegExp(r'\d').hasMatch(response[ + // 0][ + // 'display_value'] ?? + // '') + // ? '(${response[0]['display_value'] ?? 'NA'})' + // : '${response[0]['display_value'] ?? 'NA'}', + // + // style: const TextStyle( + // fontSize: 11, + // color: Colors.grey, + // overflow: + // TextOverflow.ellipsis, + // ), + // ), + // const SizedBox(height: 1), + // Text( + // response[0]['value'] ?? 'NA', + // overflow: TextOverflow + // .ellipsis, // Truncate text if it overflows + // maxLines: + // 1, // Ensures text stays in a single line + // style: TextStyle( + // fontSize: 23, + // fontWeight: FontWeight.w900, + // color: (response[0][ + // 'font_color'] ?? + // '') + // .isEmpty + // ? bodyColor + // : _getColorFromHex( + // response[0] + // ['font_color']), + // ), + // ), + // SizedBox( + // height: + // 2, // Height of the divider + // child: Divider( + // color: Color(0xFFBBBCBD), + // thickness: + // 1, // Divider line thickness + // ), + // ), + // Text( + // response[1]['value'] ?? 'NA', + // style: TextStyle( + // fontSize: 16, + // fontWeight: FontWeight.w600, + // color: (response[1][ + // 'font_color'] ?? + // '') + // .isEmpty + // ? const Color( + // 0xFFD83731) + // : _getColorFromHex( + // response[1] + // ['font_color']), + // ), + // textAlign: TextAlign + // .center, // Ensure proper alignment + // overflow: TextOverflow + // .ellipsis, // Truncate if text overflows + // ), + // Text( + // // '(${response[1]['display_value'] ?? 'NA'})', + // RegExp(r'\d').hasMatch(response[ + // 1][ + // 'display_value'] ?? + // '') + // ? '(${response[1]['display_value'] ?? 'NA'})' + // : '${response[1]['display_value'] ?? 'NA'}', + // style: const TextStyle( + // fontSize: 8, + // fontWeight: FontWeight.w500, + // color: Colors.grey, + // overflow: + // TextOverflow.ellipsis, + // ), + // ), + // ], + // ), + // ), + // ), + // ); + // } + // }, + // ), + // ), // chartsData Cards ListView.builder( itemCount: chartsData.length, @@ -2769,7 +2820,9 @@ class _ChartScreen1State extends ConsumerState { 'chart_type'] == 'bar_chart_horizontal') ? 370 - : 350, + : (chartsData[index]['chart_type'] == 'fl_stacked_bar') + ? 390 + : 350, // child: buildChart(chartsData[index]), child: ChartWidget( @@ -2901,3 +2954,391 @@ Color _getColorFromHex(String hexColor) { } return Color(int.parse(hexColor, radix: 16)); } + +class CardWidget extends StatelessWidget { + final Map card; + final Map chartScreenData; + + const CardWidget( + {Key? key, required this.card, required this.chartScreenData}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final chart_type = card['chart_type']; + final chart_heading = card['chart_heading']; + final card_full_length = card['card_full_length']; + print('cardfulllength $card_full_length'); + final response = card['response'] as List? ?? []; + final card_logo = card['card_logo']; + double cardHeight = + (chart_type == 'totals' || chart_type == 'averages') ? 180.0 : 130.0; + + final bodyColor = Color( + int.parse( + (chartScreenData['body_color'] ?? '#898C81').replaceFirst('#', '0xff'), + ), + ); + + if (response.length == 1) { + return Container( + margin: const EdgeInsets.all(10), + // width: card_full_length ? double.infinity : null, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Color(int.parse( + (chartScreenData['border_color'] ?? '#898C81') + .replaceFirst('#', '0xff'))), + // Dynamic border color + width: 1, // Adjust border thickness + ), + ), + child: Card( + margin: const EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 2, + child: Container( + // height: cardHeight, + height: 160, + padding: const EdgeInsets.only( + left: 16.0, right: 16.0, bottom: 2.0, top: 1.0), + decoration: BoxDecoration( + color: Colors.white, // Move color inside BoxDecoration + borderRadius: BorderRadius.circular( + 12), // Ensure border radius is applied + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.network( + card_logo ?? '', + width: 30, + height: 30, + errorBuilder: (context, error, stackTrace) { + return Icon(Icons.public, + color: Color(0xFF90B0D5), size: 30); // Fallback icon + }, + ), + const SizedBox(height: 1), + MouseRegion( + onEnter: (event) { + // Show tooltip on hover + final overlay = Overlay.of(context) + .context + .findRenderObject() as RenderBox; + final entry = OverlayEntry( + builder: (context) => Positioned( + left: overlay.localToGlobal(Offset.zero).dx, + top: overlay.localToGlobal(Offset.zero).dy, + child: Material( + color: Colors.transparent, + child: Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + chart_heading ?? 'NA', + style: TextStyle(color: Colors.white), + ), + ), + ), + ), + ); + Overlay.of(context).insert(entry); + Future.delayed( + Duration(seconds: 2), () => entry.remove()); + }, + child: Text( + chart_heading ?? 'NA', + textAlign: TextAlign.center, + maxLines: 2, + overflow: + TextOverflow.ellipsis, // Truncate text with '...' + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w400, + color: Colors.black87, + ), + ), + ), + const SizedBox(height: 5), + Text( + RegExp(r'\d').hasMatch(response[0]['display_value'] ?? '') + ? '(${response[0]['display_value'] ?? 'NA'})' + : '${response[0]['display_value'] ?? 'NA'}', + style: const TextStyle( + fontSize: 11, + color: Colors.grey, + overflow: + TextOverflow.ellipsis, // Truncate if text overflows + ), + maxLines: 1, // Limit to one line to prevent overflow + textAlign: TextAlign.center, // Ensure proper alignment + ), + const SizedBox(height: 1), + Row( + mainAxisAlignment: MainAxisAlignment + .center, // Center-aligns the row contents + children: [ + Text( + response[0]['value'] ?? 'NA', + textAlign: TextAlign.center, // Ensures text is centered + style: TextStyle( + fontSize: 23, + fontWeight: FontWeight.w800, + color: (response[0]['font_color'] ?? '').isEmpty + ? bodyColor + : _getColorFromHex(response[0]['font_color']), + ), + ), + const SizedBox(width: 4), // Space between text and icon + if (response[0]['font_color'] != '') ...[ + if (response[0]['font_color'] == '#D83731') + const Icon(Icons.arrow_downward, + color: Colors.red, size: 20) + else if (response[0]['font_color'] == '#11AF22') + const Icon(Icons.arrow_upward, + color: Colors.green, size: 20), + ], + ], + ) + ], + ), + ), + )); + } else { + return Container( + margin: const EdgeInsets.all(10), + // width: card_full_length ? double.infinity : null, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Color(int.parse( + (chartScreenData['border_color'] ?? '#898C81') + .replaceFirst('#', '0xff'))), // Dynamic border color + width: 1, // Adjust border thickness + ), + ), + child: Card( + margin: const EdgeInsets.all(0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 0, // Remove shadow to keep only the outli + + child: Container( + height: 160, + padding: const EdgeInsets.all(10.0), + // padding: const EdgeInsets.only( + // left: 10.0, right: 10.0, bottom: 5.0, top: 1.0), + decoration: BoxDecoration( + color: Colors.white, // Move color inside BoxDecoration + borderRadius: + BorderRadius.circular(12), // Ensure border radius is applied + ), + child: Column( + mainAxisSize: MainAxisSize.min, // Adjust card height based on content + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // const Icon(Icons.public, + // color: Color(0xFF90B0D5), size: 30), + Image.network( + card_logo ?? '', + width: 30, + height: 30, + errorBuilder: (context, error, stackTrace) { + return Icon(Icons.public, + color: Color(0xFF90B0D5), size: 30); // Fallback icon + }, + ), + const SizedBox(height: 3), + MouseRegion( + onEnter: (event) { + final overlay = Overlay.of(context); + final entry = OverlayEntry( + builder: (context) => Positioned( + left: event.position.dx, + top: event.position.dy + 10, // Adjust tooltip position + child: Material( + color: Colors.transparent, + child: Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.black87, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + chart_heading ?? 'NA', + style: + TextStyle(color: Colors.white, fontSize: 10), + ), + ), + ), + ), + ); + overlay.insert(entry); + Future.delayed(Duration(seconds: 2), () => entry.remove()); + }, + child: SizedBox( + width: double.infinity, // Ensures it uses available space + child: Text( + chart_heading ?? 'NA', + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, // Truncate with '...' + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w400, + color: Colors.black87, + ), + ), + ), + ), + const SizedBox(height: 1), + Text( + // '(${response[0]['display_value'] ?? 'NA'})', + + RegExp(r'\d').hasMatch(response[0]['display_value'] ?? '') + ? '(${response[0]['display_value'] ?? 'NA'})' + : '${response[0]['display_value'] ?? 'NA'}', + + style: const TextStyle( + fontSize: 11, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(height: 1), + + + + Row( + mainAxisAlignment: MainAxisAlignment + .center, // Center-aligns the row contents + children: [ + Text( + response[0]['value'] ?? 'NA', + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle( + fontSize: 23, + fontWeight: FontWeight.w900, + color: (response[0]['font_color'] ?? '').isEmpty + ? bodyColor + : _getColorFromHex(response[0]['font_color']), + ), + ), + const SizedBox(width: 1), // Space between text and icon + if (response[0]['font_color'] != '') ...[ + if (response[0]['font_color'] == '#D83731') + const Icon(Icons.arrow_downward, + color: Colors.red, size: 20) + else if (response[0]['font_color'] == '#11AF22') + const Icon(Icons.arrow_upward, + color: Colors.green, size: 20), + ], + ], + ), + + + SizedBox( + height: 2, // Height of the divider + width: 100, + child: Divider( + color: Color(0xFFBBBCBD), + thickness: 1, // Divider line thickness + ), + ), + + + + + Row( + mainAxisAlignment: MainAxisAlignment + .center, // Center-aligns the row contents + children: [ + Text( + response[1]['value'] ?? 'NA', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: (response[1]['font_color'] ?? '').isEmpty + ? const Color(0xFFD83731) + : _getColorFromHex(response[1]['font_color']), + ), + textAlign: TextAlign.center, // Ensure proper alignment + overflow: TextOverflow.ellipsis, // Truncate if text overflows + ), + const SizedBox(width: 1), // Space between text and icon + if (response[1]['font_color'] != '') ...[ + if (response[1]['font_color'] == '#D83731') + const Icon(Icons.arrow_downward, + color: Colors.red, size: 20) + else if (response[1]['font_color'] == '#11AF22') + const Icon(Icons.arrow_upward, + color: Colors.green, size: 20), + ], + ], + ), + + + Text( + // '(${response[1]['display_value'] ?? 'NA'})', + RegExp(r'\d').hasMatch(response[1]['display_value'] ?? '') + ? '(${response[1]['display_value'] ?? 'NA'})' + : '${response[1]['display_value'] ?? 'NA'}', + style: const TextStyle( + fontSize: 8, + fontWeight: FontWeight.w500, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + ); + } + // return Card( + // elevation: 4, + // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + // child: Padding( + // padding: const EdgeInsets.all(16.0), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Image.network( + // card['card_logo'], + // height: 50, + // width: 50, + // fit: BoxFit.contain, + // ), + // SizedBox(height: 10), + // Text( + // card['chart_heading'] ?? '', + // style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + // ), + // SizedBox(height: 10), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: List.generate(card['response'].length, (index) { + // var response = card['response'][index]; + // return Text( + // "${response['display_value']}: ${response['value']}", + // style: TextStyle(fontSize: 14), + // ); + // }), + // ), + // ], + // ), + // ), + // ); + } +} \ No newline at end of file diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index 1a8c32c7..c3a8d0b4 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -34,7 +34,7 @@ class ChartWidget extends StatelessWidget { } String formatNumberConversion( - double value, String chartConversion, String numberFormat) { + double value, String chartConversion, String numberFormat,) { // Convert the input value to base unit (actual value) double baseValue = value; @@ -175,16 +175,15 @@ class ChartWidget extends StatelessWidget { message: title, // Full text on hover child: ConstrainedBox( // Constrain width to allow wrapping - constraints: BoxConstraints(maxWidth: 130), + constraints: BoxConstraints(maxWidth: 200), child: Text( title, style: TextStyle( fontSize: 12, ), - softWrap: true, - maxLines: 2, - overflow: - TextOverflow.ellipsis, // Ensures text doesn't overflow + // softWrap: true, + // maxLines: 2, + overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow ), ), ), @@ -365,31 +364,39 @@ class ChartWidget extends StatelessWidget { }, ), ), - SizedBox(height: 105), + SizedBox(height: 45), Expanded( // child: SingleChildScrollView( // scrollDirection: Axis.horizontal, // - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Container( - width: double.infinity, - constraints: - BoxConstraints(minHeight: 3), // Allow dynamic height - child: Padding( - padding: const EdgeInsets.only( - left: 0.0, right: 0.0, bottom: 8.0, top: 1.0), - child: Wrap( - spacing: 2, - runSpacing: 5, - children: - generateIndicators(chartData, chartData['group_by']), + // child: SingleChildScrollView( + // scrollDirection: Axis.vertical, + child: Center( + child: Container( + width: double.infinity, + constraints: + BoxConstraints(minHeight: 3), // Allow dynamic height + child: Padding( + padding: const EdgeInsets.only( + left: 2.0, right: 2.0, bottom: 8.0, top: 1.0), + child: Column( // Change Row to Column + crossAxisAlignment: CrossAxisAlignment.start, + children: generateIndicators(chartData, chartData['group_by']), + ), + + + // child: Wrap( + // spacing: 2, + // runSpacing: 5, + // children: + // generateIndicators(chartData, chartData['group_by']), + // ), ), ), ), ), - ), + // ), ], ); case 'fl_stacked_bar': @@ -568,10 +575,11 @@ class ChartWidget extends StatelessWidget { ), textStyle: TextStyle(color: Colors.white), child: Text( - group.length > 10 - ? '${group.substring(0, 10)}...' - : group, - overflow: TextOverflow.ellipsis, + group, + // group.length > 10 + // ? '${group.substring(0, 10)}...' + // : group, + // overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 11), ), ) @@ -2227,7 +2235,11 @@ class ChartWidget extends StatelessWidget { _lastFormattedValue = formattedValue; // print('formattedValueLine - $formattedValue'); - return Text(formattedValue, style: TextStyle(fontSize: 10)); + return Text(formattedValue, textAlign: TextAlign.center, + style: TextStyle( + fontSize: 10, + + )); } return const SizedBox.shrink(); @@ -2374,8 +2386,7 @@ class ChartWidget extends StatelessWidget { width: 20, // width: barWidth, borderRadius: BorderRadius.zero, - color: - Colors.black // This will act as a container for stacked items + color: Colors.black // This will act as a container for stacked items ), ], ); @@ -2636,4 +2647,4 @@ class ChartData { final String? x; final double y; final DateTime? xDateTime; -} +} \ No newline at end of file diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index 68f06844..3d472bf2 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import 'package:dio/dio.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; @@ -11,6 +12,7 @@ import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/uae_numbe import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; + class BookMark extends ConsumerStatefulWidget { const BookMark({super.key}); @@ -27,18 +29,20 @@ class _BookMarkState extends ConsumerState { int selectedTabIndex = 0; // Tab categories - final List tabs = [ - 'All Bookmarks', - 'Economy', - 'Social', - 'Environment', - ]; + // final List tabs = [ + // 'All Bookmarks', + // 'Economy', + // 'Social', + // 'Environment', + // ]; + @override void initState() { super.initState(); final locale = ref.read(localeProvider); fetchBookmarks(locale?.languageCode ?? 'en'); + } String colorToHex(Color color) { @@ -263,6 +267,18 @@ class _BookMarkState extends ConsumerState { @override Widget build(BuildContext context) { + final List tabs = [ + AppLocalizations.of(context)!.all_bookmarks, + AppLocalizations.of(context)!.economy_title, + AppLocalizations.of(context)!.social_title, + AppLocalizations.of(context)!.environment_title, + ]; + + ref.listen(localeProvider, (previous, next) { + final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null + fetchBookmarks(localeCode); + }); + List> bookmarks = dataList.where((item) => item['isBookmark'] == true).toList(); List> filteredBookmarks = dataList .where((bookmark) => @@ -271,7 +287,7 @@ class _BookMarkState extends ConsumerState { print('filtered $filteredBookmarks'); return BaseScaffold( - title: Text('Bookmarks'), + title: Text(AppLocalizations.of(context)!.bookmarks,), body: Column( children: [ TabBarHeader( @@ -498,4 +514,4 @@ class TabBarHeader extends StatelessWidget { ), ); } -} +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index c56c72f3..092ea055 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.25+26 +version: 1.0.26+27 environment: sdk: ">=3.2.3 <4.0.0"