From cfe5b5bf20b8bb8880f7c8acb24fda7d64a3e6fd Mon Sep 17 00:00:00 2001 From: venbaittech Date: Tue, 25 Feb 2025 18:08:20 +0530 Subject: [PATCH 1/6] 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" From 30db38c60bb34b3c9817e6e016d6d4b3dd8a17cb Mon Sep 17 00:00:00 2001 From: Kalonkarthik Date: Wed, 26 Feb 2025 15:25:51 +0530 Subject: [PATCH 2/6] all bookmark categorized and arabic validation bug --- lib/l10n/intl_ar.arb | 4 +- .../auth_verification/create_new_pw.dart | 8 +- .../auth_verification/registration.dart | 5 +- lib/presentation/Screens/profilepage.dart | 11 +- .../routes/auth_routes/login_route.dart | 4 +- .../drawer_routes/Drawer Items/bookmark.dart | 376 ++++++++++++++++-- .../Drawer Items/user_guide/userguide.dart | 179 ++++----- 7 files changed, 448 insertions(+), 139 deletions(-) diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index 83622a31..663b028a 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -1,8 +1,8 @@ { "all_bookmarks":"كل العلامات المرجعية", - "economy_title":" الاقتصاد", + "economy_title":"اقتصاد", "social_title":"اجتماعي", - "environment_title":"البيئة", + "environment_title":"بيئة", "bookmarks": "الإشارات المرجعية", "feedback_title": "تعليق", "feedback_failed_msg": "لم يتم إرسال تعليقاتك. يرجى المحاولة مرة أخرى.", diff --git a/lib/presentation/Screens/auth_verification/create_new_pw.dart b/lib/presentation/Screens/auth_verification/create_new_pw.dart index 0b8de8da..74e345cf 100644 --- a/lib/presentation/Screens/auth_verification/create_new_pw.dart +++ b/lib/presentation/Screens/auth_verification/create_new_pw.dart @@ -32,7 +32,7 @@ class _CreateNewPwState extends ConsumerState { bool _obscureNewPassword = true; bool _obscureConfirmPassword = true; bool _isPasswordUpdated = false; // Variable to toggle UI - + bool hasValidated = false; String? _oldPassword; String? _newPassword; String? _confirmPassword; @@ -242,10 +242,11 @@ class _CreateNewPwState extends ConsumerState { pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300, onTap: () { + final formState = _formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); Future.delayed(Duration(milliseconds: 100), () { - if (formState?.validate() == false) { + if (hasValidated && formState?.validate() == false) { formState?.validate(); } }); @@ -581,6 +582,9 @@ class _CreateNewPwState extends ConsumerState { width: screenWidth / 1.1, child: ElevatedButton( onPressed: () async { + setState(() { + + }); if ((_formKey.currentState?.validate() ?? false)) { await updatePassword( widget.userId, diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index aa9166d0..4eaccccc 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -27,7 +27,7 @@ class _RegisterScreenState extends ConsumerState { final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _confirmpasswordController = TextEditingController(); - + bool hasValidated = false; bool _obscurePassword = true; bool _obscureConfirmPassword = true; bool isChecked = false; @@ -219,6 +219,7 @@ class _RegisterScreenState extends ConsumerState { if (_formKey.currentState?.validate() ?? false) { if (isChecked) { setState(() { + hasValidated = true; isRegistering = true; // Disable the button }); try { @@ -386,7 +387,7 @@ class _RegisterScreenState extends ConsumerState { final formState = _formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); Future.delayed(Duration(milliseconds: 100), () { - if (formState?.validate() == false) { + if (hasValidated && formState?.validate() == false) { formState?.validate(); } }); diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index c93f003f..3a1b8a7e 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -36,7 +36,7 @@ class ProfileScreen extends ConsumerStatefulWidget { class _ProfileScreenState extends ConsumerState { final _pb = PocketBase('https://pb.venbait.in'); // final _pb = PocketBase('http://127.0.0.1:8090'); - + bool hasValidated = false; // Add focus nodes and hint states final List _focusNodes = List.generate(4, (_) => FocusNode()); final List _showHints = [ @@ -488,7 +488,13 @@ class _ProfileScreenState extends ConsumerState { pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300, onTap: () { + final formState = _formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); + Future.delayed(Duration(milliseconds: 100), () { + if (hasValidated && formState?.validate() == false) { + formState?.validate(); + } + }); }, ); }, @@ -947,6 +953,9 @@ class _ProfileScreenState extends ConsumerState { // ElevatedButton.icon( ElevatedButton( onPressed: () { + setState(() { + hasValidated = true; + }); if ((_formKey.currentState?.validate() ?? false) && (isChecked)) { _formKey.currentState?.save(); diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index 53bbf143..549eb2e7 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -125,6 +125,7 @@ class LoginRoute extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final hasValidated = useState(false); final locale = ref.watch(localeProvider); final emailCtl = useTextEditingController(); final pwCtl = useTextEditingController(); @@ -270,6 +271,7 @@ class LoginRoute extends HookConsumerWidget { width: double.infinity, child: ElevatedButton( onPressed: () async { + hasValidated.value=true; final isValid = formKey.currentState!.validate(); if (!isValid) return; final session = await context.loaderWithErrorDialog( @@ -677,7 +679,7 @@ class LoginRoute extends HookConsumerWidget { final formState = formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); Future.delayed(Duration(milliseconds: 100), () { - if (formState?.validate() == false) { + if (hasValidated.value && formState?.validate() == false) { formState?.validate(); } }); diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index 3d472bf2..f4226a55 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -24,19 +24,11 @@ class _BookMarkState extends ConsumerState { final _pb = PocketBase('https://pb.venbait.in'); List> dataList = []; bool isLoading = true; - + Map> groupedMap = {}; + int? expandedIndex = 0; // Current selected tab index int selectedTabIndex = 0; - // Tab categories - // final List tabs = [ - // 'All Bookmarks', - // 'Economy', - // 'Social', - // 'Environment', - // ]; - - @override void initState() { super.initState(); @@ -105,8 +97,36 @@ class _BookMarkState extends ConsumerState { 'id': item['id'], }; }).toList(); - print('dataList $dataList'); + // print('dataList $dataList'); }); + groupedMap = {}; + for (var item in dataList) { + String? mainTopic = item['main_topic']; + String subtitle = item['subtitle']; + + + // Ignore if main_topic is null + if (mainTopic == null) continue; + + // If main_topic doesn't exist in groupedMap, create a new entry + if (!groupedMap.containsKey(mainTopic)) { + groupedMap[mainTopic] = {'main_topic': mainTopic, + 'valueColor': item['valueColor'], + 'SubTopic': [] + }; + } + + // Add subtitle as a key with its corresponding map value + groupedMap[mainTopic]!['SubTopic'].add ({ + 'subtitle': subtitle, + 'isBookmark': item['isBookmark'], + 'value': item['value'], + 'title':item['title'], + 'value_source':item['value_source'], + 'data_set':item['data_set'], + 'id': item['id'], + }); + } } } } catch (e) { @@ -267,11 +287,11 @@ 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, + final List> tabs = [ + { 'title':AppLocalizations.of(context)!.all_bookmarks, 'color': Colors.black}, + { 'title': AppLocalizations.of(context)!.economy_title, 'color': Colors.black}, + { 'title':AppLocalizations.of(context)!.social_title, 'color': Colors.black}, + { 'title': AppLocalizations.of(context)!.environment_title, 'color': Colors.black}, ]; ref.listen(localeProvider, (previous, next) { @@ -281,11 +301,19 @@ class _BookMarkState extends ConsumerState { List> bookmarks = dataList.where((item) => item['isBookmark'] == true).toList(); List> filteredBookmarks = dataList - .where((bookmark) => - bookmark['main_topic'].toString().trim().toLowerCase() == tabs[selectedTabIndex].toString().trim().toLowerCase()) - .toList(); + .where((bookmark) { + String mainTopic = bookmark['main_topic'].toString().trim().toLowerCase(); + String selectedTabTitle = tabs[selectedTabIndex]['title'].toString().trim().toLowerCase(); - print('filtered $filteredBookmarks'); + // Debugging prints + print("main_topic: '$mainTopic', selected_tab_title: '$selectedTabTitle'"); + + return mainTopic == selectedTabTitle; + }) + .toList(); + // print( 'filtered one :${filteredBookmarks['main_topic']} , Tabs : ${tabs[selectedTabIndex]["title"]}'); + List> transformedList = groupedMap.values.toList(); + // print('filtered $filteredBookmarks'); return BaseScaffold( title: Text(AppLocalizations.of(context)!.bookmarks,), body: Column( @@ -301,23 +329,68 @@ class _BookMarkState extends ConsumerState { ), Expanded( child: selectedTabIndex == 0 - ? Padding( - padding: const EdgeInsets.all(8.0), - child: GridView.builder( - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 10.0, - mainAxisSpacing: 10.0, - mainAxisExtent: 100, - ), - itemCount: bookmarks.length, - itemBuilder: (context, index) { - return _buildBox(bookmarks[index], context); - }, + ? (bookmarks.isNotEmpty + ? SingleChildScrollView( + child: Column( + children: List.generate(transformedList.length, (i) { + final mainTopic = transformedList[i]; + print('oustside1 $mainTopic'); + final list=List.from(mainTopic['SubTopic'] ?? []); + print('oustside2 $list'); + return CustomExpandableTile( + index: i, + isExpanded: expandedIndex == i, + onTap: (int index) { // 🔹 Expecting an index + setState(() { + expandedIndex = (expandedIndex == index) ? null : index; + }); + }, + title: mainTopic['main_topic'] ?? 'No Topic', + childWidget: + Container( + decoration: BoxDecoration( + color: Colors.white, + // borderRadius: BorderRadius.all(Radius.circular(20)) + ), + padding: const EdgeInsets.all(16), + child: GridView.builder( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + mainAxisExtent: 100, + ), + itemCount:list.length, + itemBuilder: (context, index) { + return _buildBoxes(mainTopic['SubTopic'][index], context,mainTopic['valueColor']); + }, + ), + ), + filteredBookmarks: List.from(mainTopic['SubTopic'] ?? []), titleBackgroundColor: mainTopic['valueColor'], + // Ensure it's a new list + ); + }), ), - - ):filteredBookmarks.isEmpty + ) + : Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.info_outline, + size: 100, color: Colors.grey[400]), + SizedBox(height: 16), + Text( + context.translate('No BookMark Added','لم يتم إضافة أي علامة مرجعية'), + style: + TextStyle(fontSize: 16, color: Colors.grey), + ), + ], + ), + )) + :filteredBookmarks.isEmpty ? Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -348,7 +421,6 @@ class _BookMarkState extends ConsumerState { return _buildBox(filteredBookmarks[index], context); }, ), - ), ), ], @@ -371,7 +443,7 @@ class _BookMarkState extends ConsumerState { print(hexColor); // Prints: 0xFFAA8E83 debugPrint("Box clicked: ${data['title']}"); - context.go( + context.push( '/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle'); }, child: Container( @@ -456,10 +528,110 @@ class _BookMarkState extends ConsumerState { ), ); } + + Widget _buildBoxes(Map data, BuildContext context, Color styleColor) { + // Color borderColor = data['valueColor']; + print('inside function $data'); + return GestureDetector( + onTap: () { + final data_set = data['data_set']; + + // final Color colorPattern = data['valueColor']; + final encodedMainTopic = data['main_topic']; + final encodedTitle = data['title']; + String hexColor = colorToHex(styleColor); + + debugPrint( '/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle'); + + // String hexColor = colorToHex(colorPattern); // Get hex string + // print(hexColor); // Prints: 0xFFAA8E83 + + // debugPrint("Box clicked: ${data['title']}"); + context.push( + '/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle'); + }, + child: Container( + width: MediaQuery.of(context).size.width * 0.4, + height: 100, + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: styleColor), + ), + child: + Align( + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Align( + alignment: Alignment.center, + child: Text( + data['title'] ?? '', + style: const TextStyle(fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ), + ), + GestureDetector( + onTap: () { + debugPrint("Icon clicked in: ${data['title']}"); + removeBookmark(data['id']); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text( + // context.translate('Removed From Bookmark','تمت الإزالة من العلامات المرجعية'), + // // style: TextStyle(color: Color(0xFF2F692C), + // // fontWeight: FontWeight.w500), + // ), + // // backgroundColor: Color(0xFFD6E9C6), + // duration: Duration(seconds: 2), + // ), + // ); + }, + child: SvgPicture.asset( + BookmarkAssetPath.delete, + semanticsLabel: 'share', + width:23, + height: 20, + ) + ), + ], + ), + Text( + data['value_source'] ?? '', + style: const TextStyle( + fontWeight: FontWeight.w500, color: Colors.grey), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + Text( + data['value'] ?? '', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: styleColor, + ), + ), + ], + ), + ), + ), + ); + } + } class TabBarHeader extends StatelessWidget { - final List tabs; + final List> tabs; final int selectedIndex; final ValueChanged onTabSelected; @@ -480,7 +652,7 @@ class TabBarHeader extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, children: tabs.asMap().entries.map((entry) { int index = entry.key; - String text = entry.value; + String text = entry.value['title']; return Row( children: [ TextButton( @@ -505,7 +677,7 @@ class TabBarHeader extends StatelessWidget { } Widget buildDivider() { - return Container( + return SizedBox( height: 20, child: const VerticalDivider( color: Colors.grey, @@ -514,4 +686,124 @@ class TabBarHeader extends StatelessWidget { ), ); } -} \ No newline at end of file +} + +class CustomExpandableTile extends StatefulWidget { + final String title; + final Color titleBackgroundColor; + final List filteredBookmarks; + final int index; + final bool isExpanded; + final ValueChanged onTap; + final Widget childWidget; + + const CustomExpandableTile({ + required this.title, + required this.titleBackgroundColor, + required this.filteredBookmarks, + required this.index, + required this.isExpanded, + required this.onTap, + required this.childWidget, + }); + + @override + _CustomExpandableTileState createState() => _CustomExpandableTileState(); +} + +class _CustomExpandableTileState extends State { + + @override + void initState() { + super.initState(); // Initialize isExpanded based on widget's property + } + + @override + Widget build(BuildContext context) { + double myheight = MediaQuery.of(context).size.height; + // print(widget.filteredBookmarks); + return Card( + elevation: 0, + child: Column( + children: [ + GestureDetector( + onTap: () => widget.onTap(widget.index), + child: Container( + decoration: BoxDecoration( + color: Colors.white, // Ensuring the background outside the rounded container is white + ), + child: Container( + decoration: BoxDecoration( + color: widget.titleBackgroundColor, + borderRadius: BorderRadius.all(Radius.circular(35)) + ), + padding: const EdgeInsets.only( + left: 16, bottom: 5, top: 5, right: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.title, + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w600, + fontSize: 20, + ), + ), + Icon( + widget.isExpanded + ? Icons.keyboard_arrow_up + : Icons.keyboard_arrow_down, + color: Colors.white, + size: 28.0, + ), + ], + ), + ), + ), + ), + ClipRRect( + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + width: double.infinity, + color: Colors.white, + height:widget.isExpanded ? myheight * 0.4 : 0, + child:widget.isExpanded + ? SingleChildScrollView( + child: Column( + children: [ + widget.childWidget, + // Container( + // decoration: BoxDecoration( + // color: Colors.white, + // // borderRadius: BorderRadius.all(Radius.circular(20)) + // ), + // padding: const EdgeInsets.all(16), + // child: GridView.builder( + // shrinkWrap: true, + // physics: NeverScrollableScrollPhysics(), + // gridDelegate: + // const SliverGridDelegateWithFixedCrossAxisCount( + // crossAxisCount: 2, + // crossAxisSpacing: 10.0, + // mainAxisSpacing: 10.0, + // mainAxisExtent: 100, + // ), + // itemCount: widget.filteredBookmarks.length, + // itemBuilder: (context, index) { + // return _buildBox(widget.filteredBookmarks[index], context,widget.titleBackgroundColor); + // }, + // ), + // ), + ], + ), + ) + : null, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart index b6372bcb..cb25a3ef 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart @@ -7,7 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class Userguide extends StatefulWidget { - const Userguide({super.key}); + Userguide({super.key}); @override State createState() => _UserguideState(); @@ -20,6 +20,7 @@ class _UserguideState extends State { {'routePath':'faq','color': Color(0xFF7296BE), 'text': 'FAQs', 'icon': 'mdi:faq', 'text-ar': 'لأسئلة الشائعة'}, ]; + @override Widget buildDynamicWidget(dynamic icons, Color color) { if (icons is IconData) { return Icon( @@ -46,41 +47,41 @@ class _UserguideState extends State { } } - @override Widget build(BuildContext context) { return PopScope( - canPop: false, - onPopInvokedWithResult: (didPop, result) { - if (didPop) return; - context.go('/myhomepage'); - }, - child: BaseScaffold( - showDivider: true, - bottomColor: Colors.white, - dividerColor: Colors.grey[300], - appbarColor: Colors.white, - title: Text(AppLocalizations.of(context)!.guide_title) , - body: Container( - color: Colors.white, - padding: const EdgeInsets.symmetric(horizontal: 16 , vertical: 20), - child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, // Two columns - crossAxisSpacing: 10.0, - mainAxisSpacing: 10.0, - mainAxisExtent:MediaQuery.of(context).size.height* 0.15 , + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + showDivider: true, + bottomColor: Colors.white, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + title: Text(AppLocalizations.of(context)!.guide_title) , + body: Container( + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 16 , vertical: 20), + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + childAspectRatio: 1.7, + // mainAxisExtent:MediaQuery.of(context).size.height* 0.15 , + ), + itemCount: guideList.length, + itemBuilder: (context, index) { + return HoverContainer( + iconName: guideList[index]['icon'], + title: context.translate(guideList[index]['text'], guideList[index]['text-ar']), + routePath: guideList[index]['routePath'], + ); + }, ), - itemCount: guideList.length, - itemBuilder: (context, index) { - return HoverContainer( - iconName: guideList[index]['icon'], - title: context.translate(guideList[index]['text'], guideList[index]['text-ar']), - routePath: guideList[index]['routePath'], - ); - }, ), ), - ), ); } @@ -108,69 +109,69 @@ class _HoverContainerState extends State { return GestureDetector( onTap: () { context.push('/user-guide/${widget.routePath}');}, child: MouseRegion( - onEnter: (_) => setState(() => isHovered = true), - onExit: (_) => setState(() => isHovered = true), - child : Container( - padding: EdgeInsets.only(top: 4, right: 4, left: 4, bottom: 6), - height: screenHeight* 0.23 , - width: screenWidth*0.30, - margin: EdgeInsets.all(1), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - boxShadow: isHovered - ? [ - BoxShadow( - color: Colors.black.withValues(alpha:0.2), - blurRadius:2, - spreadRadius: 1, - offset: Offset(0, 4), - ), - ] - : [], - border: Border.all( - color: Color(0xFF7DAFBC), - width: 1.0, - ), - ), - alignment: Alignment.center, - // duration: Duration(milliseconds: 200), + onEnter: (_) => setState(() => isHovered = true), + onExit: (_) => setState(() => isHovered = true), + child : Container( + padding: EdgeInsets.only(top: 4, right: 4, left: 4, bottom: 6), - child: LayoutBuilder(builder: (context, constraints){ - double containerWidth = constraints.maxWidth; - // double containerHeight = constraints.maxHeight; - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconifyIcon(icon: widget.iconName, - color: Color((0xFF7DAFBC)), - size: containerWidth * 0.25,), - // buildDynamicWidget(data['icon'], Color(0xFF7DAFBC)), - SizedBox(width: 10,height: containerWidth * 0.04,), // Space between icon and text - Container( - width: containerWidth* 0.85, - padding: EdgeInsets.symmetric(horizontal: 4, vertical: 4), - margin: EdgeInsets.only(bottom: 3), - decoration: BoxDecoration( - color: Color(0xFF7DAFBC), - borderRadius: BorderRadius.circular(5), - border: Border.all(color: Color(0xFF7DAFBC)), - ), - child: Text( - widget.title, - style: TextStyle( - color: Colors.white, // Text color - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, + width: screenWidth*0.30, + margin: EdgeInsets.all(1), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: isHovered + ? [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius:2, + spreadRadius: 1, + offset: Offset(0, 4), ), + ] + : [], + border: Border.all( + color: Color(0xFF7DAFBC), + width: 1.0 ), - ], - ); - },), + ), + alignment: Alignment.center, + // duration: Duration(milliseconds: 200), + + child: LayoutBuilder(builder: (context, constraints){ + double containerWidth = constraints.maxWidth; + double containerHeight = constraints.maxHeight; + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconifyIcon(icon: widget.iconName, + color: Color((0xFF7DAFBC)), + size: containerHeight * 0.45,), + // buildDynamicWidget(data['icon'], Color(0xFF7DAFBC)), + SizedBox(width: 10,height: containerHeight * 0.04,), // Space between icon and text + Container( + width: containerWidth* 0.85, + padding: EdgeInsets.symmetric(horizontal: 4, vertical: 4), + margin: EdgeInsets.only(bottom: 3), + decoration: BoxDecoration( + color: Color(0xFF7DAFBC), + borderRadius: BorderRadius.circular(5), + border: Border.all(color: Color(0xFF7DAFBC)) + ), + child: Text( + widget.title, + style: TextStyle( + color: Colors.white, // Text color + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + ), + ], + ); + }) - ), + ), ), From ca24970c53fd01acc52139cfe059dfcff4445254 Mon Sep 17 00:00:00 2001 From: Kalonkarthik Date: Thu, 27 Feb 2025 17:33:22 +0530 Subject: [PATCH 3/6] svg icons replaced,validate msg aligned,bookmark haeding added etc --- assets/icons/misc/Search.svg | 3 + assets/icons/uae_numbers/Filter.svg | 3 + .../icons/misc_icon_asset_path.dart | 2 +- .../icons/uae_numbers_asset_path.dart | 3 +- .../UAE_Numbers/uae_numbers.dart | 13 +++-- .../auth_verification/create_new_pw.dart | 5 +- .../auth_verification/registration.dart | 8 ++- .../Screens/charts/screens/chart_screen.dart | 22 +++---- lib/presentation/Screens/profilepage.dart | 9 ++- .../components/themed_text_field.dart | 2 +- .../drawer_routes/Drawer Items/bookmark.dart | 58 ++++++++++++++----- .../Drawer Items/manage_users.dart | 14 +++-- 12 files changed, 96 insertions(+), 46 deletions(-) create mode 100644 assets/icons/misc/Search.svg create mode 100644 assets/icons/uae_numbers/Filter.svg diff --git a/assets/icons/misc/Search.svg b/assets/icons/misc/Search.svg new file mode 100644 index 00000000..076d7f9a --- /dev/null +++ b/assets/icons/misc/Search.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/uae_numbers/Filter.svg b/assets/icons/uae_numbers/Filter.svg new file mode 100644 index 00000000..131ae70c --- /dev/null +++ b/assets/icons/uae_numbers/Filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart b/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart index 0b01da5f..3b1a35a7 100644 --- a/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart +++ b/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart @@ -12,5 +12,5 @@ abstract class MiscIconAssetPath { static const save = '$_basePath/save.png'; static const group = '$_basePath/group.png'; static const search = '$_basePath/search.png'; - + static const Search = '$_basePath/Search.svg'; } diff --git a/lib/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart b/lib/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart index 167127df..6cec49e3 100644 --- a/lib/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart +++ b/lib/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart @@ -6,5 +6,6 @@ abstract class UaeNumbersAssetPath { // static const bookmarksSelectedUae = '$_basePath/bookmarksSelectedUae.png'; // static const shareUae = '$_basePath/share.png'; static const share = '$_basePath/share.svg'; - static const filterUae = '$_basePath/filters.png'; + static const filterUae = '$_basePath/filters.png'; + static const filterCharts = '$_basePath/Filter.svg'; } 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 c3940cf7..0c825532 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 @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; @@ -197,11 +198,13 @@ class _UaenumberWidgetState extends ConsumerState { decoration: InputDecoration( hintText: "Search", hintStyle: TextStyle(color: Color(0xFF898C81)), - - prefixIcon: Image( - image: ExactAssetImage(MiscIconAssetPath.search), - width: 24, - height: 24, + prefixIconConstraints: BoxConstraints(maxWidth: 42, maxHeight: 42), + prefixIcon: Container( + padding: EdgeInsets.only(right: 5), + child: SvgPicture.asset( + MiscIconAssetPath.Search, + semanticsLabel: 'Search', + ), ), // prefixIcon: Image.asset( diff --git a/lib/presentation/Screens/auth_verification/create_new_pw.dart b/lib/presentation/Screens/auth_verification/create_new_pw.dart index 74e345cf..8b279121 100644 --- a/lib/presentation/Screens/auth_verification/create_new_pw.dart +++ b/lib/presentation/Screens/auth_verification/create_new_pw.dart @@ -242,11 +242,12 @@ class _CreateNewPwState extends ConsumerState { pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300, onTap: () { - + print('has validated $hasValidated'); final formState = _formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); Future.delayed(Duration(milliseconds: 100), () { if (hasValidated && formState?.validate() == false) { + print('has validated $hasValidated'); formState?.validate(); } }); @@ -583,7 +584,7 @@ class _CreateNewPwState extends ConsumerState { child: ElevatedButton( onPressed: () async { setState(() { - + hasValidated=true; }); if ((_formKey.currentState?.validate() ?? false)) { await updatePassword( diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index 4eaccccc..a3528dbb 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -216,10 +216,12 @@ class _RegisterScreenState extends ConsumerState { } Future _registerUser() async { + setState(() { + hasValidated = true; + }); if (_formKey.currentState?.validate() ?? false) { if (isChecked) { setState(() { - hasValidated = true; isRegistering = true; // Disable the button }); try { @@ -1111,11 +1113,11 @@ class _RegisterScreenState extends ConsumerState { ?.languageCode == 'ar' ? 0 - : 30.0, + : 40.0, right: registerLocale ?.languageCode == 'ar' - ? 40 + ? 45 : 0.0,), child: Text( context.translate('Required', 'مطلوب'), diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index dacfc19f..bc15c581 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1459,11 +1459,12 @@ class _ChartScreen1State extends ConsumerState { children: [ Row( children: [ - Image.asset( - UaeNumbersAssetPath.filterUae, - color: Color(0xFF8E8E8E), // Outline color - width: 24, // Slightly larger - height: 24, + SvgPicture.asset( + UaeNumbersAssetPath.filterCharts, + semanticsLabel: 'Filter', + colorFilter:ColorFilter.mode(Color(0xFF8E8E8E),BlendMode.srcIn), + width: 25, + height: 25, ), SizedBox(width: 8), Text( @@ -2172,12 +2173,11 @@ class _ChartScreen1State extends ConsumerState { ), ), SizedBox(width: 10), - Image.asset( - UaeNumbersAssetPath.filterUae, - color: Colors - .white, // Set color to white - width: 21, - height: 21, + SvgPicture.asset( + UaeNumbersAssetPath.filterCharts, + semanticsLabel: 'Filter', + width: 24, + height: 24, ), ], ), diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index 3a1b8a7e..d52a6f55 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -456,6 +456,7 @@ class _ProfileScreenState extends ConsumerState { @override Widget build(BuildContext context) { + final profileLocale = ref.watch(localeProvider); return PopScope( canPop: false, // Allow back navigation only if not login screen onPopInvokedWithResult: (didPop, result) { @@ -790,7 +791,7 @@ class _ProfileScreenState extends ConsumerState { ), borderRadius: BorderRadius.circular(8), ), - labelText: 'Select', + labelText: context.translate('Select',' اختيار') ), icon: Icon(Icons.keyboard_arrow_down_sharp, color: @@ -916,7 +917,11 @@ class _ProfileScreenState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(left: 10.0), + padding: EdgeInsets.only(left: 10.0, right: profileLocale + ?.languageCode == + 'ar' + ? 15 + : 0.0,), child: Text( context.translate('Required', 'مطلوب'), style: TextStyle( diff --git a/lib/presentation/components/themed_text_field.dart b/lib/presentation/components/themed_text_field.dart index 82b58ce6..843a7876 100644 --- a/lib/presentation/components/themed_text_field.dart +++ b/lib/presentation/components/themed_text_field.dart @@ -45,7 +45,7 @@ class ThemedFormField extends HookWidget { final inputDecoration = InputDecoration( filled: true, fillColor: Colors.white, - contentPadding: const EdgeInsets.symmetric(vertical: 14), + contentPadding: const EdgeInsets.symmetric(vertical: 14, horizontal: 15), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide( diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index f4226a55..fd2cc5ab 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -289,9 +289,9 @@ class _BookMarkState extends ConsumerState { final List> tabs = [ { 'title':AppLocalizations.of(context)!.all_bookmarks, 'color': Colors.black}, - { 'title': AppLocalizations.of(context)!.economy_title, 'color': Colors.black}, - { 'title':AppLocalizations.of(context)!.social_title, 'color': Colors.black}, - { 'title': AppLocalizations.of(context)!.environment_title, 'color': Colors.black}, + { 'title': AppLocalizations.of(context)!.economy_title, 'color': Color(0xFF90B0D5)}, + { 'title':AppLocalizations.of(context)!.social_title, 'color': Color(0xFFAA8E83)}, + { 'title': AppLocalizations.of(context)!.environment_title, 'color': Color(0xFF7DAFBC)}, ]; ref.listen(localeProvider, (previous, next) { @@ -408,19 +408,47 @@ class _BookMarkState extends ConsumerState { ) : Padding( padding: const EdgeInsets.all(8.0), - child: GridView.builder( - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 10.0, - mainAxisSpacing: 10.0, - mainAxisExtent: 100, + child: Column( + children: [ + Container( + decoration: BoxDecoration( + color: tabs[selectedTabIndex]['color'], + borderRadius: BorderRadius.all(Radius.circular(35)) + ), + padding: const EdgeInsets.only( + left: 16, bottom: 5, top: 5, right: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + tabs[selectedTabIndex]['title'], + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w600, + fontSize: 20, + ), ), - itemCount: filteredBookmarks.length, - itemBuilder: (context, index) { - return _buildBox(filteredBookmarks[index], context); - }, + ], + ), + ), + SizedBox(height: 20,), + Expanded( + child: GridView.builder( + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + mainAxisExtent: 100, ), + itemCount: filteredBookmarks.length, + itemBuilder: (context, index) { + return _buildBox(filteredBookmarks[index], context); + }, + ), + ), + ], + ), ), ), ], @@ -661,7 +689,7 @@ class TabBarHeader extends StatelessWidget { foregroundColor: MaterialStateProperty.resolveWith((states) { return selectedIndex == index - ? Colors.black + ? entry.value['color'] : Colors.grey[700]; }), ), 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 164957bb..30d826c8 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; @@ -342,11 +343,14 @@ class _ManageUserRouterState extends State { decoration: InputDecoration( hintText: "Search", hintStyle: TextStyle(color: Color(0xFF898C81)), - prefixIcon: Image( - image: ExactAssetImage(MiscIconAssetPath.search), - width: 24, - height: 24, - color: Color(0xFFAA8E83)), + prefixIconConstraints: BoxConstraints(maxWidth: 42, maxHeight: 42), + prefixIcon: Container( + padding: EdgeInsets.only(right: 5), + child: SvgPicture.asset( + MiscIconAssetPath.Search, + semanticsLabel: 'Search', + ), + ), // prefixIcon: Image.asset( // MiscIconAssetPath.search, From d7a1b5aa385966d8d6f7f57e00cdf73d079fc6c7 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Fri, 28 Feb 2025 09:01:52 +0530 Subject: [PATCH 4/6] chart api changes and dev pocketbase url --- android/app/build.gradle | 4 +- lib/config/api_config.dart | 3 + lib/config/my_router.dart | 26 + .../services/pocketbase_service.dart | 4 +- lib/l10n/intl_ar.arb | 1 + lib/l10n/intl_en.arb | 2 +- lib/main.dart | 12 + .../UAE_Numbers/uae_numbers.dart | 4 +- .../auth_verification/changepassword.dart | 7 +- .../auth_verification/confirm_password.dart | 3 +- .../auth_verification/create_new_pw.dart | 3 +- .../auth_verification/otp_verification.dart | 3 +- .../auth_verification/registration.dart | 3 +- .../Screens/charts/screens/chart_screen.dart | 613 ++++-------------- .../Screens/charts/services/api_service.dart | 42 +- .../Screens/charts/widgets/chart_widget.dart | 181 ++++-- lib/presentation/Screens/profilepage.dart | 3 +- .../routes/auth_routes/login_route.dart | 7 +- .../tab_routes/home_route.dart | 8 +- .../drawer_routes/Drawer Items/bookmark.dart | 7 +- .../Drawer Items/edit_profile.dart | 5 +- .../drawer_routes/Drawer Items/feedback.dart | 3 +- .../Drawer Items/manage_users.dart | 3 +- .../notification/notification.dart | 3 +- .../drawer_routes/custom_drawer_routes.dart | 8 +- .../routes/drawer_routes/feedback_route.dart | 3 +- pubspec.yaml | 2 +- 27 files changed, 386 insertions(+), 577 deletions(-) create mode 100644 lib/config/api_config.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index a74f4048..64443c26 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 = "27" + flutterVersionCode = "28" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.26" + flutterVersionName = "1.0.27" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/lib/config/api_config.dart b/lib/config/api_config.dart new file mode 100644 index 00000000..07b7c7f4 --- /dev/null +++ b/lib/config/api_config.dart @@ -0,0 +1,3 @@ +// api_config.dart +// const String apiUrl = 'http://192.168.1.26:8090'; +const String apiUrl = 'https://pbdev.venbait.in/'; diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index 1130fe03..00f2c6a0 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -292,6 +292,8 @@ // return router; // } +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; @@ -414,11 +416,33 @@ final GoRouter router = GoRouter( final mainTopic = state.uri.queryParameters['mainTopic'] ?? ''; final title = state.uri.queryParameters['title'] ?? ''; final key = state.uri.queryParameters['key'] ?? ''; + final kpi = state.uri.queryParameters['kpi'] ?? ''; // Get kpi + + // Parse filter_data as a JSON list + // Parse filter_data as a JSON list + List> filterData = []; + + if (state.uri.queryParameters.containsKey('filter_data') && + state.uri.queryParameters['filter_data']!.isNotEmpty) { + try { + filterData = List>.from( + jsonDecode(state.uri.queryParameters['filter_data']!) + ); + } catch (e) { + print('Error parsing filter_data: $e'); + filterData = []; // Assign an empty list to prevent null issues + } + } else { + filterData = []; // Ensure it's a valid list + } + + print('Router dataSets: $dataSets'); print('Router bgColor: $bgColor'); print('Router mainTopic: $mainTopic'); print('Router title: $title'); + print('Router filter: $filterData'); // Pass both values to the screen return ChartScreen1( @@ -427,6 +451,8 @@ final GoRouter router = GoRouter( mainTopic: mainTopic, title: title, keyParam: key, + kpi: kpi, + filter_data: filterData, ); }, ), diff --git a/lib/infrastructure/services/pocketbase_service.dart b/lib/infrastructure/services/pocketbase_service.dart index 20fb6ace..017137df 100644 --- a/lib/infrastructure/services/pocketbase_service.dart +++ b/lib/infrastructure/services/pocketbase_service.dart @@ -1,9 +1,11 @@ import 'dart:convert'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; abstract class PocketBaseService { - static const _host = 'https://pb.venbait.in'; + static const _host = apiUrl; + // static const _host = 'https://pb.venbait.in'; // static const _host = 'http://127.0.0.1:8090'; static final _pb = PocketBase(_host); static final users = _pb.collection('users'); diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index 83622a31..c6b55469 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -4,6 +4,7 @@ "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 90c050e0..10d131d5 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,10 +1,10 @@ { - "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", diff --git a/lib/main.dart b/lib/main.dart index d58dbe2d..a795ed32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,8 @@ import 'package:uae_stat/presentation/Screens/auth_verification/registration.dar import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + + // void main() async { // WidgetsFlutterBinding.ensureInitialized(); // // await (await SharedPreferences.getInstance()).clear(); @@ -89,6 +91,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // } // } + + void main() async { WidgetsFlutterBinding.ensureInitialized(); configureDependencies(); @@ -102,10 +106,18 @@ void main() async { class MainApp extends ConsumerWidget { const MainApp({super.key}); + + + @override Widget build(BuildContext context, WidgetRef ref) { final locale = ref.watch(localeProvider); + final connectivityProvider = Provider((ref) { + return true; // Replace with actual logic + }); + + // ref.listen(connectivityProvider, (previous, hasInternet) { // print('Previous Internet Status: $previous'); // print('Current Internet Status: $hasInternet'); 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 c3940cf7..86daad93 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 @@ -10,6 +10,8 @@ import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_r import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:uae_stat/presentation/components/constant/constant.dart'; import 'package:http/http.dart' as http; +import 'package:uae_stat/config/api_config.dart'; + class UaeNumbers extends StatelessWidget { const UaeNumbers({super.key}); @@ -83,7 +85,7 @@ class _UaenumberWidgetState extends ConsumerState { Future fetchData(locale) async { // const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; - const baseUrl = 'https://pb.venbait.in/api/getUAENumbersData'; + const baseUrl = '$apiUrl/api/getUAENumbersData'; try { final response = await http.get(Uri.parse(baseUrl + '?language=$locale')); if (response.statusCode == 200) { diff --git a/lib/presentation/Screens/auth_verification/changepassword.dart b/lib/presentation/Screens/auth_verification/changepassword.dart index 225c143a..c23170e8 100644 --- a/lib/presentation/Screens/auth_verification/changepassword.dart +++ b/lib/presentation/Screens/auth_verification/changepassword.dart @@ -5,6 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'otp_verification.dart'; class Changepassword extends StatefulWidget { @@ -17,7 +18,7 @@ class Changepassword extends StatefulWidget { } class _ResetPasswordScreenState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final pb = PocketBase('http://127.0.0.1:8090'); final _formKey = GlobalKey(); final _emailController = TextEditingController(); @@ -46,7 +47,7 @@ class _ResetPasswordScreenState extends State { // Check if email exists in the user collection final userCheckResponse = await http.get( Uri.parse( - 'https://pb.venbait.in/api/collections/users/records?filter=email="$email"'), + '$apiUrl/api/collections/users/records?filter=email="$email"'), headers: { 'Authorization': 'Bearer $authToken', }, @@ -63,7 +64,7 @@ class _ResetPasswordScreenState extends State { // Proceed with OTP request final otpResponse = await http.post( Uri.parse( - 'https://pb.venbait.in/api/collections/otp_requests/records'), + '$apiUrl/api/collections/otp_requests/records'), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer $authToken', diff --git a/lib/presentation/Screens/auth_verification/confirm_password.dart b/lib/presentation/Screens/auth_verification/confirm_password.dart index cef960e0..2cf9b323 100644 --- a/lib/presentation/Screens/auth_verification/confirm_password.dart +++ b/lib/presentation/Screens/auth_verification/confirm_password.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/presentation/Screens/profilepage.dart'; class ConfirmPassword extends StatefulWidget { @@ -12,7 +13,7 @@ class ConfirmPassword extends StatefulWidget { } class _ConfirmPasswordState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final pb = PocketBase('http://127.0.0.1:8090'); final _formKey = GlobalKey(); bool _obscurePassword = true; diff --git a/lib/presentation/Screens/auth_verification/create_new_pw.dart b/lib/presentation/Screens/auth_verification/create_new_pw.dart index 0b8de8da..a0303f4a 100644 --- a/lib/presentation/Screens/auth_verification/create_new_pw.dart +++ b/lib/presentation/Screens/auth_verification/create_new_pw.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_router.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; @@ -26,7 +27,7 @@ class CreateNewPw extends ConsumerStatefulWidget { } class _CreateNewPwState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); final _formKey = GlobalKey(); bool _obscureOldPassword = true; bool _obscureNewPassword = true; diff --git a/lib/presentation/Screens/auth_verification/otp_verification.dart b/lib/presentation/Screens/auth_verification/otp_verification.dart index f5c4c6c8..a6c1c309 100644 --- a/lib/presentation/Screens/auth_verification/otp_verification.dart +++ b/lib/presentation/Screens/auth_verification/otp_verification.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'confirm_password.dart'; @@ -24,7 +25,7 @@ class EmailVerificationScreen extends StatefulWidget { class _EmailVerificationScreenState extends State { // final pb = PocketBase('http://127.0.0.1:8090'); - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); final List _otpControllers = List.generate(4, (_) => TextEditingController()); int _secondsRemaining = 120; // 2 minutes timer diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index aa9166d0..e9faf1f5 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; @@ -38,7 +39,7 @@ class _RegisterScreenState extends ConsumerState { bool isRegistering = false; dynamic userID; - final pb = PocketBase('https://pb.venbait.in'); + final pb = PocketBase(apiUrl); // final pb = PocketBase('http://127.0.0.1:8090'); // Add focus nodes and hint states diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index dacfc19f..ab95b72b 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -8,6 +10,7 @@ import 'package:pocketbase/pocketbase.dart'; import 'package:screenshot/screenshot.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/toast_util.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart'; @@ -31,6 +34,8 @@ class ChartScreen1 extends ConsumerStatefulWidget { final String mainTopic; final String title; final String? keyParam; // Nullable String + final String kpi; + final List> filter_data; const ChartScreen1({ Key? key, @@ -39,13 +44,16 @@ class ChartScreen1 extends ConsumerStatefulWidget { required this.mainTopic, required this.title, required this.keyParam, + required this.kpi, + required this.filter_data, }); @override ConsumerState createState() => _ChartScreen1State(); } class _ChartScreen1State extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List> selectedFiltersStorage = []; final GlobalKey _scaffoldKey = GlobalKey(); final ApiService apiService = ApiService(); @@ -67,6 +75,9 @@ class _ChartScreen1State extends ConsumerState { late Color backgroundColor; final ScrollController _scrollController = ScrollController(); int _activeTabIndex = 0; + dynamic tabWiseKpi=[]; + dynamic tabFilteredKpi=[]; + List> formattedFilters=[]; dynamic _tabsData = []; // List> _tabsData = []; @@ -85,11 +96,12 @@ class _ChartScreen1State extends ConsumerState { super.initState(); final String bgColor = widget.bgColor; print(' bgColor $bgColor'); - // fetchChartData(widget.dataSets); checkIfBookmarked(); locale = ref.read(localeProvider) ?? const Locale('en'); - fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) { - if (_tabsData.isNotEmpty) { + + fetchChartData(widget.dataSets, locale?.languageCode ?? 'en', widget.kpi, widget.filter_data) + .then((_) { + if(_tabsData.isNotEmpty) { // Call onTabSelected for the first tab onTabSelected(_tabsData[0]['id']); } @@ -1202,6 +1214,8 @@ class _ChartScreen1State extends ConsumerState { // } void processChartData(chartsData) { + print("PROCESSING FILTER CHART DATa"); + // Group data by 'kpi' Map>> groupedData = {}; @@ -1231,7 +1245,6 @@ class _ChartScreen1State extends ConsumerState { ? word[0].toUpperCase() + word.substring(1) : '') // Capitalize .join(' '); // Join words with space - return {'id': kpi, 'name': tabHeading, 'order': tabOrder.toString()}; }).toList(); @@ -1244,7 +1257,7 @@ class _ChartScreen1State extends ConsumerState { print('Sorted Tabs: $_tabs'); - print('Grouped Data: $groupedData'); + // print('Grouped Data: $groupedData'); print('Tabs: $_tabs'); setState(() { @@ -1252,8 +1265,13 @@ class _ChartScreen1State extends ConsumerState { }); } - Future fetchChartData(String dataSets, locale) async { - var data = await apiService.fetchChartData(dataSets, locale); + Future fetchChartData(String dataSets, locale, kpi, filter_data ) async { + var data = await apiService.fetchChartData(dataSets, locale,kpi,filter_data); + + tabFilteredKpi = kpi; + print('FETCH KPI- $kpi'); + print('FETCH KFilter- $filter_data'); + if (data.containsKey('filterData')) { var filterData = data['filterData']; @@ -1281,18 +1299,71 @@ class _ChartScreen1State extends ConsumerState { processChartData(chartsData); + onTabSelected(tabFilteredKpi); + print('chartsData :- $chartsData'); print('cardData :- $cardData'); print('chartScreenData :- $chartScreenData'); // print('filterData :- $filterData'); isLoading = false; }); - print('chartsData -$chartsData'); - print('cardData -$cardData'); + // print('chartsData -$chartsData'); + // print('cardData -$cardData'); } void applyFilters(BuildContext context, List filters, List data, List dataCard, List selectedFilters) { + + print('applyFilters called'); + print('Selected ApplyFilters: $selectedFilters'); + + if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) { + setState(() { + chartsData = + List.from(originalTabChartsData); // Restore the original data + // cardData = List.from(originalTabCardData); // Restore the original data + }); + print('Returning as no filters are selected'); + Navigator.pop(context); + return; // Exit early since all filter_data are empty + } + + // Transform the selectedFilters list into the required format + formattedFilters = selectedFilters + .where((filter) => filter['filter_data'] != null && filter['filter_data'].isNotEmpty) + .map((filter){ + return{ + 'filter_key': filter['filter_key'], + 'filter_data':filter['filter_data'].map((item)=> item.toString()).toList() + }; + }).toList(); + + print('Formatted Filters1: $formattedFilters'); + + // Convert to JSON format + String selectedFormatFilters = jsonEncode({ + 'kpi': tabWiseKpi, + 'filter_data': formattedFilters + }); + + print('Formatted Filters2: $selectedFormatFilters'); + + // Call fetchChartData with correct parameters + fetchChartData( + widget.dataSets, + locale.languageCode ?? 'en', + tabWiseKpi, // Ensure you are passing the correct KPI here + formattedFilters // Pass the formatted filter data here + ); + Navigator.pop(context); + + selectedFiltersStorage = List.from(selectedFilters); + print('selectedFiltersStoraged- $selectedFiltersStorage'); + + } + + void applyFilters1(BuildContext context, List filters, List data, + List dataCard, List selectedFilters) { print("applyFilters called"); print("Selected ApplyFilters: $selectedFilters"); print("Selected data: $data"); @@ -1429,6 +1500,9 @@ class _ChartScreen1State extends ConsumerState { } void showRightSideModal(BuildContext context, List filters, List data) { + + print('selectedFiltersStoraged1- $selectedFiltersStorage'); + // Initialize selected filters structure from the stored value, if exists List> selectedFilters = selectedFiltersStorage.isNotEmpty @@ -1437,6 +1511,8 @@ class _ChartScreen1State extends ConsumerState { return {"filter_key": filter["filter_key"], "filter_data": []}; }).toList(); // Or initialize empty filters + print('selectedFiltersStoragedrgt- $selectedFiltersStorage'); + showModalBottomSheet( context: context, isScrollControlled: true, @@ -1706,6 +1782,13 @@ class _ChartScreen1State extends ConsumerState { cardData = List.from(originalTabCardData); }); selectedFiltersStorage.clear(); + formattedFilters = []; + fetchChartData( + widget.dataSets, + locale.languageCode ?? 'en', + tabWiseKpi, // Ensure you are passing the correct KPI here + formattedFilters // Pass the formatted filter data here + ); Navigator.pop(context); }, style: ElevatedButton.styleFrom( @@ -1738,6 +1821,7 @@ class _ChartScreen1State extends ConsumerState { onPressed: () { print( "Selected Filters before applying: $selectedFilters"); + setState(() { chartsData = originalTabChartsData; cardData = originalTabCardData; @@ -1745,7 +1829,7 @@ class _ChartScreen1State extends ConsumerState { applyFilters(context, filters, chartsData, cardData, selectedFilters); - selectedFiltersStorage = List.from(selectedFilters); + // selectedFiltersStorage = List.from(selectedFilters); }, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF92722A), @@ -1787,8 +1871,10 @@ class _ChartScreen1State extends ConsumerState { } void onTabSelected(String tabId) { - print('Selected Tab: $tabId'); - selectedFiltersStorage.clear(); + print('Selected Tab on: $tabId'); + tabWiseKpi = tabId; + + // selectedFiltersStorage.clear(); // Filter the filterDataSet filterData = filterDataSet .where((item) => item['key'] == tabId) @@ -1824,7 +1910,8 @@ class _ChartScreen1State extends ConsumerState { } void performActionForTab(String tabId) { - print('Selected Tab: $tabId'); + + print('Selected Tab perform: $tabId'); // Filter the chartsData array based on the tabId tabFilteredChartData = chartsData.where((chart) { @@ -1920,12 +2007,18 @@ class _ChartScreen1State extends ConsumerState { final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null // fetchChartData(widget.dataSets, localeCode); - fetchChartData(widget.dataSets, localeCode).then((_) { + + final List> safeFilterData = widget.filter_data ?? []; + final String safeKpi = widget.kpi ?? ''; + fetchChartData(widget.dataSets,localeCode, safeKpi, safeFilterData).then((_) { + print('DEBUG KPI: $safeKpi'); if (_tabsData.isNotEmpty) { // Call onTabSelected for the first tab onTabSelected(_tabsData[0]['id']); } }); + + }); double myheight = MediaQuery.of(context).size.height; double mywidth = MediaQuery.of(context).size.width; @@ -2303,483 +2396,6 @@ class _ChartScreen1State extends ConsumerState { }, ), ), - // 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, shrinkWrap: true, @@ -2818,7 +2434,7 @@ class _ChartScreen1State extends ConsumerState { ? 500 : (chartsData[index][ 'chart_type'] == - 'bar_chart_horizontal') + 'bar_chart_horizontal') ? 370 : (chartsData[index]['chart_type'] == 'fl_stacked_bar') ? 390 @@ -2980,7 +2596,12 @@ class CardWidget extends StatelessWidget { ), ); - if (response.length == 1) { + + if(response.isEmpty) + { + return SizedBox.shrink(); + } + else if (response.length == 1) { return Container( margin: const EdgeInsets.all(10), // width: card_full_length ? double.infinity : null, @@ -3117,7 +2738,7 @@ class CardWidget extends StatelessWidget { margin: const EdgeInsets.all(10), // width: card_full_length ? double.infinity : null, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(12), border: Border.all( color: Color(int.parse( (chartScreenData['border_color'] ?? '#898C81') @@ -3341,4 +2962,4 @@ class CardWidget extends StatelessWidget { // ), // ); } -} \ No newline at end of file +} diff --git a/lib/presentation/Screens/charts/services/api_service.dart b/lib/presentation/Screens/charts/services/api_service.dart index 196aed85..dfc29379 100644 --- a/lib/presentation/Screens/charts/services/api_service.dart +++ b/lib/presentation/Screens/charts/services/api_service.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'dart:collection'; +import 'package:uae_stat/config/api_config.dart'; + class ChartData { final DateTime? xDateTime; final String? x; // Optional for non-DateTime-based charts @@ -11,19 +13,49 @@ class ChartData { } class ApiService { - static const String baseUrl = 'https://pb.venbait.in/api/getDataSet'; + // static const String baseUrl = 'https://pb.venbait.in/api/getDataSet'; + static const String baseUrl = '$apiUrl/api/getDataSet'; - Future> fetchChartData(String dataSets, locale) async { + Future> fetchChartData(String dataSets, locale,kpi, + List> filterData) async { List isChartData = []; List nonChartData = []; List originalChartsData = []; List originalCardData = []; - final url = Uri.parse('$baseUrl?dataset=$dataSets&language=$locale'); + // final url = Uri.parse('$baseUrl?dataset=$dataSets&language=$locale'); + // final url = Uri.parse( + // '$baseUrl?dataset=$dataSets&language=$locale&kpi=$kpi&filter_data=${Uri.encodeComponent(jsonEncode(filterData))}' + // ); + + + final url = Uri.parse(baseUrl); // No query parameters in URL for POST + + final Map requestBody = { + 'dataset': dataSets, + 'language': locale, + 'kpi': kpi.isNotEmpty ? kpi : null, // Avoid sending empty kpi + 'filter_data': filterData.isNotEmpty ? filterData : null, // Avoid empty list + }; + + // final url = Uri.https('$baseUrl?dataset=$dataSets&language=$locale'); + + print('APISErvice - $url'); try { - final response = await http.get(url); - print('data'); + final response = await http.post( + url, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode(requestBody), + ); + + print('Response Status: ${response.statusCode}'); + print('Response Body: ${response.body}'); + + print('data -$response'); + print('API Request URL: $url'); + print('Filter Data: ${jsonEncode(filterData)}'); + if (response.statusCode == 200) { final Map jsonData = jsonDecode(response.body); // Variables to store filtered data diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index c3a8d0b4..8c95e730 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -91,6 +91,18 @@ class ChartWidget extends StatelessWidget { }).toList(); } + Color adjustColor(Color baseColor, int index) { + final HSLColor hsl = HSLColor.fromColor(baseColor); + + // Lightness variation (keeping it light, between 0.6 and 0.9) + double lightnessFactor = 0.6 + (index % 4) * 0.1; // Varies between 0.6 to 0.8 + final HSLColor adjustedHSL = hsl.withLightness( + lightnessFactor.clamp(0.6, 0.9), // Ensures light shades only + ); + + return adjustedHSL.toColor(); + } + List parsePieChartData( dynamic chartData, double totalValue, @@ -111,7 +123,7 @@ class ChartWidget extends StatelessWidget { if (rawValue is String) { value = double.tryParse(rawValue) ?? 0.0; - } else if (rawValue is int) { + } else if (rawValue is num) { value = rawValue.toDouble(); } else if (rawValue is double) { value = rawValue; @@ -125,7 +137,8 @@ class ChartWidget extends StatelessWidget { return PieChartSectionData( value: value, - color: Colors.primaries[index % Colors.primaries.length], + // color: Colors.primaries[index % Colors.primaries.length], + color: adjustColor(bodyColor, index), // Adjust alpha dynamically title: '${percentage.toStringAsFixed(1)}%', radius: isTouched ? 60 : 50, @@ -157,7 +170,7 @@ class ChartWidget extends StatelessWidget { width: 10, height: 10, decoration: BoxDecoration( - color: color, + color: adjustColor(bodyColor, index), shape: BoxShape.circle, ), ), @@ -404,6 +417,7 @@ class ChartWidget extends StatelessWidget { List groupByValuesList = groupByValues.toList(); int chunkSize = 5; List> chunkedGroupByValues = []; + print('flStackedBar1'); for (int i = 0; i < groupByValuesList.length; i += chunkSize) { chunkedGroupByValues.add( groupByValuesList.sublist( @@ -452,6 +466,8 @@ class ChartWidget extends StatelessWidget { getTooltipItem: (groupData, groupIndex, rodData, rodIndex) { // Get the list of group names dynamically + + List groupNames = []; for (var entry in chartData['response']) { String groupValue = entry['ObsKey'][groupByKey]; @@ -459,7 +475,6 @@ class ChartWidget extends StatelessWidget { groupNames.add(groupValue); } } - // Accessing the stacked rod items and calculating the tooltip text List rodStackItems = rodData.rodStackItems; @@ -486,6 +501,8 @@ class ChartWidget extends StatelessWidget { Color groupColor = _getColorForGroup( i); // Replace with your color logic + + // Add a TextSpan for the colored circle and the group name with value tooltipTextSpans.addAll([ TextSpan( @@ -682,18 +699,8 @@ class ChartWidget extends StatelessWidget { } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { // Year-MonthAbbr (2019-Nov) Map monthMap = { - 'Jan': 1, - 'Feb': 2, - 'Mar': 3, - 'Apr': 4, - 'May': 5, - 'Jun': 6, - 'Jul': 7, - 'Aug': 8, - 'Sep': 9, - 'Oct': 10, - 'Nov': 11, - 'Dec': 12 + 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, + 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12 }; List parts = timePeriod.split('-'); @@ -951,9 +958,13 @@ class ChartWidget extends StatelessWidget { (entry) => double.parse(entry['ObsKey']['TIME_PERIOD'])) .toSet(); + print('uniqueXValuesLineTrend2- $uniqueXValues'); + // Generate line bars for the chart List lineBars = lineBarsData2(filteredData); + + return Column(children: [ Text( chartData['chart_heading'] ?? '', @@ -979,8 +990,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) + - 50, // Adjust width dynamically + width: (uniqueXValues.length * 50) + 50, // Adjust width dynamically child: LineChart( LineChartData( lineTouchData: lineTouchData1(), @@ -1227,7 +1237,7 @@ class ChartWidget extends StatelessWidget { } return Container(); }, - reservedSize: 80, + reservedSize: 110, ), ), topTitles: AxisTitles( @@ -1253,13 +1263,13 @@ class ChartWidget extends StatelessWidget { barRods: [ BarChartRodData( toY: yAxisData[index], - color: Colors.blueAccent, + color: bodyColor, borderRadius: BorderRadius.circular(4), width: 20, ), ], showingTooltipIndicators: [0], - ), + ), ), ), )) @@ -1268,8 +1278,36 @@ class ChartWidget extends StatelessWidget { // Extract groupBy values and their corresponding y-axis values List xAxisData = []; List yAxisData = []; + List> sortedData = []; for (var entry in chartData['response']) { + String? timePeriod = entry['ObsKey']['TIME_PERIOD']; + if (timePeriod != null) { + // Check if it contains a month (i.e., has "-" and follows "YYYY-MM" format) + bool hasMonth = RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod); + + if (hasMonth) { + print('Yes-TIME_PERIOD: $timePeriod'); + sortedData.add(entry); + } else { + print('No-TIME_PERIOD: $timePeriod'); + } + } + } + // Sort the data based on year and month + sortedData.sort((a, b) { + String timeA = a['ObsKey']['TIME_PERIOD']; + String timeB = b['ObsKey']['TIME_PERIOD']; + + return timeA.compareTo(timeB); // Lexicographical sorting works for YYYY-MM + }); + + // If no valid TIME_PERIOD with a month is found, return original response + List> finalData = sortedData.isNotEmpty ? sortedData : List.from(chartData['response']); + + + for (var entry in finalData) { + var xValue = entry['ObsKey'][groupByKey]; var yValue = entry['ObsValue']['Value']; if (xValue != null && yValue != null) { @@ -1277,8 +1315,11 @@ class ChartWidget extends StatelessWidget { yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); } } + print("chartData['chart_heading']"); - print(chartData['chart_heading']); + print('RESpns- ${chartData['chart_heading']}'); + print(chartData['response']); + int rotationTurns = 1; return Column(children: [ Text( @@ -1424,6 +1465,9 @@ class ChartWidget extends StatelessWidget { const double barWidth = 30; // Width for each bar, including spacing return totalBars * barWidth; // Calculate total chart width } + + print('multi_bar'); + String cropKey = chartData['chart_type_json']['x_sub_group']; // Group crops by CROP_TYPE Map> groupedCrops = {}; @@ -1462,6 +1506,8 @@ class ChartWidget extends StatelessWidget { // // print('groupedCropsflmutli- $groupedCrops'); + print('hormulti_bar'); + return Center( child: Column(children: [ Text( @@ -1503,7 +1549,7 @@ class ChartWidget extends StatelessWidget { bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, - reservedSize: 40, // Added space for rotated titles + reservedSize: 80, // Added space for rotated titles getTitlesWidget: (value, meta) { if (value < groupByValues.length) { String title = @@ -1514,12 +1560,11 @@ class ChartWidget extends StatelessWidget { : title; return Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.only(top: 8.0,left: 30.0), child: SizedBox( - width: - 60, // Limit width to force wrapping + width: 60, // Limit width to force wrapping child: Transform.rotate( - angle: -0.5, + angle: -1.5, child: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( @@ -1529,15 +1574,15 @@ class ChartWidget extends StatelessWidget { 8), // Optional: rounded corners ), textStyle: TextStyle( - color: Colors - .white), // Change text color + color: Colors.white), // Change text color ), child: Tooltip( message: title, child: Text( displayTitle, softWrap: true, - // style: TextStyle(backgroundColor: Colors.blueGrey[800]), + maxLines:2 , + style: TextStyle(fontSize: 10), overflow: TextOverflow.ellipsis, )), ), @@ -1973,6 +2018,7 @@ class ChartWidget extends StatelessWidget { 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; @@ -1980,9 +2026,9 @@ class ChartWidget extends StatelessWidget { yearGenderMap[year] = {'M': 0.0, 'F': 0.0}; } - if (gender == 'Male') { + if (gender == 'Male'|| gender == 'ذكر') { yearGenderMap[year]!['M'] = value; - } else if (gender == 'Female') { + } else if (gender == 'Female' || gender == 'أنثى') { yearGenderMap[year]!['F'] = value; } } @@ -1996,6 +2042,7 @@ class ChartWidget extends StatelessWidget { } }); + // Add a line for the ratio data lineBars.add( LineChartBarData( @@ -2105,7 +2152,22 @@ class ChartWidget extends StatelessWidget { // Use the timePeriod directly as a string for x-axis double xValue = parseTimePeriod(timePeriod); - double yValue = double.parse(entry['ObsValue']['Value']); + print('spotss'); + + // double yValue = double.parse(entry['ObsValue']['Value']); + double yValue; + var value = entry['ObsValue']['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}"); + } + return FlSpot(xValue, yValue); }).toList(); @@ -2194,7 +2256,7 @@ class ChartWidget extends StatelessWidget { } FlTitlesData titlesData1(Set xValues) { - print('tileDATa1xvalue - $xValues'); + print('tileDATa1xvalueline2 - $xValues'); double findClosest(double value, Set values) { return values @@ -2209,10 +2271,13 @@ class ChartWidget extends StatelessWidget { getTitlesWidget: (value, meta) { // Format values as millions (M) String formattedValue; + print('LineTrend2val1 - $value '); if (value % 10 == 0) { // Check if the value is in the millions or thousands range - + if (kDebugMode) { + print('LineTrend2valKmode - $value '); + } if (value >= 1000000000000) { formattedValue = '${(value / 1000000000000).toStringAsFixed(0)}T'; @@ -2244,7 +2309,7 @@ class ChartWidget extends StatelessWidget { return const SizedBox.shrink(); // return Text( - // formattedValue, + // 'LINETRENTD2', // style: TextStyle(color: Colors.black, fontSize: 12), // ); }, @@ -2256,13 +2321,13 @@ class ChartWidget extends StatelessWidget { interval: null, // interval: 10, // Ensure each year is shown only once getTitlesWidget: (value, meta) { - print('BtmTiles :-$value'); - print('BtmTilesmeta :-$meta'); + // print('BtmTiles :-$value'); + // print('BtmTilesmeta :-$meta'); // if (xValues.contains(value)) double closestValue = findClosest(value, xValues); if ((closestValue - value).abs() < 0.15) { - print("Bottomtiles"); - print(value); + // print("Bottomtiles"); + // print(value); return Padding( padding: const EdgeInsets.only(top: 1.1), child: Transform.rotate( @@ -2321,12 +2386,26 @@ class ChartWidget extends StatelessWidget { List _generateBarGroups( BuildContext context, dynamic chartData, String groupByKey) { Map> groupedData = {}; - + print('flStackedBar3'); // Group data by `group_by` and `TIME_PERIOD`, accumulating the values for each group and year for (var entry in chartData['response']) { String groupValue = entry['ObsKey'][groupByKey]; String timePeriod = entry['ObsKey']['TIME_PERIOD']; - double value = double.tryParse(entry['ObsValue']['Value']) ?? 0.0; + // double value = double.tryParse(entry['ObsValue']['Value']) ?? 0.0; + + double value; + var rawValue = entry['ObsValue']['Value']; + + if (rawValue is num) { + value = rawValue.toDouble(); + } else if (rawValue is double) { + value = rawValue; + } else { + value = double.tryParse(rawValue.toString()) ?? 0.0; + } + + + print('flStackedBar3.1'); // print('fl_groupValue $groupValue'); // print('fl_timePeriod $timePeriod'); @@ -2335,6 +2414,7 @@ class ChartWidget extends StatelessWidget { if (!groupedData.containsKey(groupValue)) { groupedData[groupValue] = {}; } + if (!groupedData[groupValue]!.containsKey(timePeriod)) { groupedData[groupValue]![timePeriod] = 0.0; } @@ -2347,6 +2427,7 @@ class ChartWidget extends StatelessWidget { List timePeriods = groupedData.values.first.keys.toList(); print('timePeriods $timePeriods'); + // double barWidth = calculateBarWidth(context, timePeriods.length); // For each time period, generate a BarChartGroupData @@ -2360,7 +2441,6 @@ class ChartWidget extends StatelessWidget { int groupIndex = 0; // Track group index for color assignment for (var group in groupedData.keys) { double value = groupedData[group]![timePeriods[i]] ?? 0.0; - // Add stacked item with current `toY` value and the incremented one rodStackItems.add( BarChartRodStackItem( @@ -2496,11 +2576,17 @@ class ChartWidget extends StatelessWidget { double _calculateMaxY(dynamic chartData) { // Dynamically calculate the maximum Y value + + print('hormulti_bar2'); + List response = chartData['response'] ?? []; double maxY = 0; for (var entry in response) { - double value = double.tryParse(entry['ObsValue']['Value'] ?? '0') ?? 0; + // double value = double.tryParse(entry['ObsValue']['Value'] ?? '0') ?? 0; + double value = (entry['ObsValue']['Value'] as num?)?.toDouble() ?? 0; + + if (value > maxY) { maxY = value; } @@ -2514,6 +2600,9 @@ class ChartWidget extends StatelessWidget { List responseData = chartData['response']; List barGroups = []; int colorIndex = 0; + + print('hormulti_bar1.1'); + // Iterate through groupByValues and populate BarChartGroupData for (int i = 0; i < groupByValues.length; i++) { String groupValue = groupByValues.elementAt(i); @@ -2528,7 +2617,7 @@ class ChartWidget extends StatelessWidget { // Ensure to retrieve and parse 'ObsValue' value (which should be a double) double value = double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; - + print('multi_bar1.1'); final List uniqueColorsForTwo = [ Color(0xFF648CBA), Color(0xFF90B0D5), @@ -2647,4 +2736,4 @@ class ChartData { final String? x; final double y; final DateTime? xDateTime; -} \ No newline at end of file +} diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index c93f003f..194aa8bc 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -12,6 +12,7 @@ import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/data/p_auth_repo.dart'; @@ -34,7 +35,7 @@ class ProfileScreen extends ConsumerStatefulWidget { } class _ProfileScreenState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final _pb = PocketBase('http://127.0.0.1:8090'); // Add focus nodes and hint states diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index 53bbf143..c7a386dd 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -25,13 +25,15 @@ import 'package:http/http.dart' as http; import '../../Screens/auth_verification/registration.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:uae_stat/config/api_config.dart'; import '../../components/indicators/locale_provider.dart'; import '../../components/my_toggle.dart'; class LoginRoute extends HookConsumerWidget { - final pb = PocketBase('https://pb.venbait.in'); + // final pb = PocketBase('https://pb.venbait.in'); + final pb = PocketBase(apiUrl); final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); // final _pb = PocketBase('http://127.0.0.1:8090'); // final bool isLoginScreen; // Pass `true` if this is the login screen @@ -342,7 +344,8 @@ class LoginRoute extends HookConsumerWidget { final userId = session.id; if (userId.isNotEmpty) { final url = - Uri.parse("https://pb.venbait.in/api/login_success?id=$userId"); + // Uri.parse("https://pb.venbait.in/api/login_success?id=$userId"); + Uri.parse('$apiUrl/api/login_success?id=$userId'); try { final response = await http.get(url); 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 3a3bd377..61b1714e 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 @@ -167,6 +167,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/data/p_auth_repo.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; @@ -176,6 +177,7 @@ import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes. import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:http/http.dart' as http; +import 'package:uae_stat/config/api_config.dart'; class MyHomePage extends ConsumerStatefulWidget { const MyHomePage({super.key}); @@ -344,7 +346,8 @@ class EconomyStatsWidget extends ConsumerStatefulWidget { class EconomyStatsState extends ConsumerState { List data = []; - final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); bool isLoading = true; final GlobalKey cardTopicKey = GlobalKey(); @@ -1077,7 +1080,8 @@ class EconomyStatsState extends ConsumerState { // } Future fetchData(locale) async { - const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; + // const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; + const baseUrl = '$apiUrl/api/getHomePageData'; try { final response = await http.get(Uri.parse(baseUrl + '?language=$locale')); if (response.statusCode == 200) { diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index 3d472bf2..f4489c09 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -6,6 +6,7 @@ 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/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/bookmark_asset_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart'; @@ -21,7 +22,7 @@ class BookMark extends ConsumerStatefulWidget { } class _BookMarkState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List> dataList = []; bool isLoading = true; @@ -77,7 +78,7 @@ class _BookMarkState extends ConsumerState { } final response = await Dio().get( - 'https://pb.venbait.in/api/getUserBookmark', + '$apiUrl/api/getUserBookmark', queryParameters: {'user_id': userID, 'language': locale}, ); @@ -514,4 +515,4 @@ class TabBarHeader extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart index 7b291815..fd90a183 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart @@ -12,6 +12,7 @@ import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; @@ -25,7 +26,7 @@ class EditProfile extends StatefulWidget { } class _EditProfileState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final _pb = PocketBase('http://127.0.0.1:8090'); bool _isProfileCompleted = false; bool _isLoading = false; @@ -203,7 +204,7 @@ class _EditProfileState extends State { if (avatarFilename.isNotEmpty && recordId.isNotEmpty) { _avatarUrl = - 'https://pb.venbait.in/api/files/$collectionId/$recordId/$avatarFilename'; + '$apiUrl/$collectionId/$recordId/$avatarFilename'; } else { _avatarUrl = ''; // Reset to default or empty } diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart b/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart index 5ea7e374..20830c6c 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart @@ -7,6 +7,7 @@ import 'package:intl/intl.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/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/feedback_asset_path.dart'; @@ -30,7 +31,7 @@ class FeedbackForm extends StatefulWidget { class _FeedbackFormState extends State with WidgetsBindingObserver { final _pb = - PocketBase('https://pb.venbait.in'); // Initialize PocketBase client + PocketBase(apiUrl); // Initialize PocketBase client // final _pb = // PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client 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 164957bb..7113e72b 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart'; @@ -16,7 +17,7 @@ class ManageUserRouter extends StatefulWidget { } class _ManageUserRouterState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List userData = []; int _sortColumnIndex = 0; bool _isAscending = true; diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart b/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart index 7fe036ed..c1b276cb 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import '../../custom_drawer_routes.dart'; class NotificationPage extends StatefulWidget { @@ -11,7 +12,7 @@ class NotificationPage extends StatefulWidget { class _NotificationPageState extends State { // Example notification data - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List> notifications = []; // Current selected tab index diff --git a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart index 96209340..322e04bc 100644 --- a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart +++ b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart @@ -24,6 +24,7 @@ import 'package:uae_stat/presentation/components/my_toggle.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:uae_stat/presentation/components/my_toggle.dart'; +import 'package:uae_stat/config/api_config.dart'; class BaseScaffold extends ConsumerStatefulWidget { const BaseScaffold({ @@ -58,7 +59,8 @@ class BaseScaffold extends ConsumerStatefulWidget { } class _BaseScaffoldState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); String _avatarUrl = ''; dynamic userId; String? userName; @@ -658,7 +660,7 @@ class _BaseScaffoldState extends ConsumerState { if (userAvatar!.isNotEmpty && recordId.isNotEmpty) { _avatarUrl = - 'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar'; + '$apiUrl/api/files/$collectionId/$recordId/$userAvatar'; } else { _avatarUrl = ''; // Reset to default or empty } @@ -704,7 +706,7 @@ class _BaseScaffoldState extends ConsumerState { title: Padding( padding: EdgeInsets.only(top: 10), child: Align( - alignment: Alignment.centerLeft, + alignment: (locale?.languageCode == 'ar') ? Alignment.centerRight : Alignment.centerLeft, child: DefaultTextStyle( style: TextStyle( color: widget.colorChange ? Colors.white : Color(0xFF414042), diff --git a/lib/presentation/routes/drawer_routes/feedback_route.dart b/lib/presentation/routes/drawer_routes/feedback_route.dart index d23f43fa..02cc918e 100644 --- a/lib/presentation/routes/drawer_routes/feedback_route.dart +++ b/lib/presentation/routes/drawer_routes/feedback_route.dart @@ -6,6 +6,7 @@ import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/packages/go_router.dart'; import 'package:uae_stat/presentation/components/my_drawer.dart'; @@ -28,7 +29,7 @@ class FeedbackForm extends StatefulWidget { class _FeedbackFormState extends State with WidgetsBindingObserver { final _pb = - PocketBase('https://pb.venbait.in'); // Initialize PocketBase client + PocketBase(apiUrl); // Initialize PocketBase client // final _pb = // PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client diff --git a/pubspec.yaml b/pubspec.yaml index 092ea055..4248f8ff 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.26+27 +version: 1.0.27+28 environment: sdk: ">=3.2.3 <4.0.0" From de820662f75e57ca43a406354d5bc980e0e5dff8 Mon Sep 17 00:00:00 2001 From: Kalonkarthik Date: Fri, 28 Feb 2025 12:31:34 +0530 Subject: [PATCH 5/6] bookmark message color change --- .../auth_verification/create_new_pw.dart | 50 +++-- .../Screens/charts/screens/chart_screen.dart | 179 +++++++++--------- lib/presentation/Screens/profilepage.dart | 10 +- .../drawer_routes/Drawer Items/bookmark.dart | 30 +-- 4 files changed, 127 insertions(+), 142 deletions(-) diff --git a/lib/presentation/Screens/auth_verification/create_new_pw.dart b/lib/presentation/Screens/auth_verification/create_new_pw.dart index e8391ba0..3d0ad519 100644 --- a/lib/presentation/Screens/auth_verification/create_new_pw.dart +++ b/lib/presentation/Screens/auth_verification/create_new_pw.dart @@ -6,6 +6,7 @@ import 'package:pocketbase/pocketbase.dart'; import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_router.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; +import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; import 'package:uae_stat/presentation/Screens/profilepage.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; @@ -13,7 +14,7 @@ import 'package:uae_stat/presentation/components/my_toggle.dart'; import 'package:uae_stat/presentation/components/space.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import '../../../config/my_theme.dart'; +import 'package:uae_stat/config/my_theme.dart'; class CreateNewPw extends ConsumerStatefulWidget { final String userId; @@ -38,6 +39,11 @@ class _CreateNewPwState extends ConsumerState { String? _newPassword; String? _confirmPassword; + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 40, + ); + String? _validateOldPassword(String? value) { if (value == null || value.isEmpty) { return AppLocalizations.of(context)!.old_password_is_required; @@ -624,16 +630,17 @@ class _CreateNewPwState extends ConsumerState { ), SizedBox(height: screenHeight / 5), Center( - child: Container( - height: screenHeight / 16, - width: screenWidth / 2.5, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/splash_screen/logo.png"), - fit: BoxFit.fill, - ), - ), - ), + // child: Container( + // height: screenHeight / 16, + // width: screenWidth / 2.5, + // decoration: BoxDecoration( + // image: DecorationImage( + // image: AssetImage("assets/splash_screen/logo.png"), + // fit: BoxFit.fill, + // ), + // ), + // ), + child: fcscBanner, ), ], ), @@ -718,16 +725,17 @@ class _CreateNewPwState extends ConsumerState { ), SizedBox(height: screenHeight / 2.2), Center( - child: Container( - height: 40, - width: screenWidth / 2.5, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/splash_screen/logo.png"), - fit: BoxFit.fill, - ), - ), - ), + // child: Container( + // height: 40, + // width: screenWidth / 2.5, + // decoration: BoxDecoration( + // image: DecorationImage( + // image: AssetImage("assets/splash_screen/logo.png"), + // fit: BoxFit.fill, + // ), + // ), + // ), + child: fcscBanner, ), ], ), diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index a2487614..692800f1 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -171,10 +171,7 @@ class _ChartScreen1State extends ConsumerState { SnackBar( content: Text( AppLocalizations.of(context)!.added_to_Bookmark, - style: TextStyle( - color: Color(0xFF2F692C), fontWeight: FontWeight.w600), ), - backgroundColor: Color(0xFFD6E9C6), duration: Duration(seconds: 2), ), ); @@ -185,10 +182,10 @@ class _ChartScreen1State extends ConsumerState { SnackBar( content: Text( AppLocalizations.of(context)!.failed_To_Remove, - style: TextStyle( - color: Color(0xFF544C4C), fontWeight: FontWeight.w600), + // style: TextStyle( + // color: Color(0xFF544C4C), fontWeight: FontWeight.w600), ), - backgroundColor: Color(0xFFEB5F24), + // backgroundColor: Color(0xFFEB5F24), duration: Duration(seconds: 2), ), ); @@ -217,10 +214,7 @@ class _ChartScreen1State extends ConsumerState { SnackBar( content: Text( AppLocalizations.of(context)!.removed_from_Bookmark, - style: TextStyle( - color: Color(0xFF2F692C), fontWeight: FontWeight.w600), ), - backgroundColor: Color(0xFFD6E9C6), duration: Duration(seconds: 2), ), ); @@ -231,10 +225,10 @@ class _ChartScreen1State extends ConsumerState { SnackBar( content: Text( 'Failed to Remove', - style: TextStyle( - color: Color(0xFF544C4C), fontWeight: FontWeight.w600), + // style: TextStyle( + // color: Color(0xFF544C4C), fontWeight: FontWeight.w600), ), - backgroundColor: Color(0xFFEB5F24), + // backgroundColor: Color(0xFFEB5F24), duration: Duration(seconds: 2), ), ); @@ -282,49 +276,55 @@ class _ChartScreen1State extends ConsumerState { ), actions: [ SizedBox(height: 20), - SizedBox( - width: 100, // Set the desired width - child: TextButton( - onPressed: () => Navigator.pop(context), - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 10.0), // Adjust the radius as needed - ), - side: BorderSide( - color: Color(0xFFAA8E83), // Set the outline color - width: 1, // Set the border width + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 100, // Set the desired width + child: TextButton( + onPressed: () => Navigator.pop(context), + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 10.0), // Adjust the radius as needed + ), + side: BorderSide( + color: Color(0xFFAA8E83), // Set the outline color + width: 1, // Set the border width + ), + ), + child: Text( + context.translate('No', 'لا'), + style: TextStyle( + color: Color(0xFFAA8E83), + fontSize: 16, + ), + ), ), ), - child: Text( - context.translate('No', 'لا'), - style: TextStyle( - color: Color(0xFFAA8E83), - fontSize: 16, + SizedBox( + width: 100, // Set the desired width + child: TextButton( + onPressed: () { + Navigator.pop(context); + removeBookmark(); // Close dialog + }, + style: TextButton.styleFrom( + backgroundColor: Color(0xFFAA8E83), // Set background color + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), // Set text color + ), + ), + child: Text( + context.translate('Yes', 'نعم'), + style: TextStyle(color: Colors.white, fontSize: 16), + ), ), ), - ), - ), - SizedBox( - width: 100, // Set the desired width - child: TextButton( - onPressed: () { - Navigator.pop(context); - removeBookmark(); // Close dialog - }, - style: TextButton.styleFrom( - backgroundColor: Color(0xFFAA8E83), // Set background color - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), // Set text color - ), - ), - child: Text( - context.translate('Yes', 'نعم'), - style: TextStyle(color: Colors.white, fontSize: 16), - ), - ), - ), + ], + ) + ], ), ); @@ -369,48 +369,51 @@ class _ChartScreen1State extends ConsumerState { ), actions: [ SizedBox(height: 20), - SizedBox( - width: 100, // Set the desired width - child: TextButton( - onPressed: () => Navigator.pop(context), - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 10.0), // Adjust the radius as needed + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ SizedBox( + width: 100, // Set the desired width + child: TextButton( + onPressed: () => Navigator.pop(context), + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 10.0), // Adjust the radius as needed + ), + side: BorderSide( + color: Color(0xFFAA8E83), // Set the outline color + width: 1, // Set the border width + ), ), - side: BorderSide( - color: Color(0xFFAA8E83), // Set the outline color - width: 1, // Set the border width - ), - ), - child: Text( - context.translate('No', 'لا'), - style: TextStyle( - color: Color(0xFFAA8E83), - fontSize: 16, + child: Text( + context.translate('No', 'لا'), + style: TextStyle( + color: Color(0xFFAA8E83), + fontSize: 16, + ), ), ), ), - ), - SizedBox( - width: 100, // Set the desired width - child: TextButton( - onPressed: () { - Navigator.pop(context); - addBookmark(); // Close dialog - }, - style: TextButton.styleFrom( - backgroundColor: Color(0xFFAA8E83), // Set background color - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), // Set text color + SizedBox( + width: 100, // Set the desired width + child: TextButton( + onPressed: () { + Navigator.pop(context); + addBookmark(); // Close dialog + }, + style: TextButton.styleFrom( + backgroundColor: Color(0xFFAA8E83), // Set background color + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), // Set text color + ), + ), + child: Text( + context.translate('Yes', 'نعم'), + style: TextStyle(color: Colors.white, fontSize: 16), + ), ), - ), - child: Text( - context.translate('Yes', 'نعم'), - style: TextStyle(color: Colors.white, fontSize: 16), - ), - ), + ),], ), ], ), diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index 104b5e24..bbdc7403 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -1018,7 +1018,7 @@ class ConfirmationDialog extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Text( - "Are you sure you want to save this page?", + AppLocalizations.of(context)!.sure_save_page, style: const TextStyle( fontSize: 14, color: Color(0xFF898C81), @@ -1030,7 +1030,7 @@ class ConfirmationDialog extends StatelessWidget { SizedBox(height: 8), Text.rich( TextSpan( - text: "Once saved, you will not be able to change your ", + text: AppLocalizations.of(context)!.not_able_to_change, style: TextStyle( fontSize: 14, color: Color(0xFF898C81), @@ -1039,15 +1039,15 @@ class ConfirmationDialog extends StatelessWidget { ), children: [ TextSpan( - text: "Name", + text: AppLocalizations.of(context)!.name, style: TextStyle(fontWeight: FontWeight.w700), // Bold for "name" ), TextSpan( - text: " or ", + text: context.translate(' or ','أو'), ), TextSpan( - text: "Date of birth", + text: AppLocalizations.of(context)!.dob, style: TextStyle( fontWeight: FontWeight.w700), // Bold for "date of birth" ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index 510d727d..a3c79491 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -151,18 +151,6 @@ class _BookMarkState extends ConsumerState { await _pb.collection('bookmark').delete(bookmarkId!, headers: { 'Authorization': adminToken, }); - // Show success SnackBar - // ScaffoldMessenger.of(context).showSnackBar( - // const SnackBar( - // content: Text( - // 'Removed from Bookmark.', - // style: TextStyle( - // color: Color(0xFF2F692C), fontWeight: FontWeight.w600), - // ), - // backgroundColor: Color(0xFFD6E9C6), - // duration: Duration(seconds: 2), - // ), - // ); final locale = ref.read(localeProvider); fetchBookmarks(locale?.languageCode ?? 'en'); // ToastUtil.showSuccessToast("Removed from Bookmark."); @@ -170,11 +158,8 @@ class _BookMarkState extends ConsumerState { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - 'Removed From Bookmark', - style: TextStyle(color: Color(0xFF2F692C), - fontWeight: FontWeight.w500), + AppLocalizations.of(context)!.removed_from_Bookmark, ), - backgroundColor: Color(0xFFD6E9C6), duration: Duration(seconds: 2), ), ); @@ -613,18 +598,7 @@ class _BookMarkState extends ConsumerState { GestureDetector( onTap: () { debugPrint("Icon clicked in: ${data['title']}"); - removeBookmark(data['id']); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text( - // context.translate('Removed From Bookmark','تمت الإزالة من العلامات المرجعية'), - // // style: TextStyle(color: Color(0xFF2F692C), - // // fontWeight: FontWeight.w500), - // ), - // // backgroundColor: Color(0xFFD6E9C6), - // duration: Duration(seconds: 2), - // ), - // ); + showRemoveBookmarkDialog(data['id']); }, child: SvgPicture.asset( BookmarkAssetPath.delete, From bbae4b5789a9992d01223f49fd6628db59a59ae6 Mon Sep 17 00:00:00 2001 From: Kalonkarthik Date: Fri, 28 Feb 2025 18:04:45 +0530 Subject: [PATCH 6/6] Contact page created --- assets/icons/enquiry/at.svg | 10 ++ assets/icons/enquiry/building.svg | 3 + assets/icons/enquiry/fax.svg | 3 + assets/icons/enquiry/map.svg | 10 ++ assets/icons/enquiry/phone.svg | 3 + lib/config/my_router.dart | 6 + .../icons/enquiry_asset_icon_path.dart | 8 + .../drawer_routes/Drawer Items/contactUs.dart | 145 ++++++++++++++++++ .../drawer_routes/custom_drawer_routes.dart | 5 + pubspec.yaml | 1 + 10 files changed, 194 insertions(+) create mode 100644 assets/icons/enquiry/at.svg create mode 100644 assets/icons/enquiry/building.svg create mode 100644 assets/icons/enquiry/fax.svg create mode 100644 assets/icons/enquiry/map.svg create mode 100644 assets/icons/enquiry/phone.svg create mode 100644 lib/infrastructure/services/img_asset_paths/icons/enquiry_asset_icon_path.dart create mode 100644 lib/presentation/routes/drawer_routes/Drawer Items/contactUs.dart diff --git a/assets/icons/enquiry/at.svg b/assets/icons/enquiry/at.svg new file mode 100644 index 00000000..a3517c93 --- /dev/null +++ b/assets/icons/enquiry/at.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/enquiry/building.svg b/assets/icons/enquiry/building.svg new file mode 100644 index 00000000..5974d94d --- /dev/null +++ b/assets/icons/enquiry/building.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/enquiry/fax.svg b/assets/icons/enquiry/fax.svg new file mode 100644 index 00000000..39a5ca7b --- /dev/null +++ b/assets/icons/enquiry/fax.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/enquiry/map.svg b/assets/icons/enquiry/map.svg new file mode 100644 index 00000000..2f42121a --- /dev/null +++ b/assets/icons/enquiry/map.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/enquiry/phone.svg b/assets/icons/enquiry/phone.svg new file mode 100644 index 00000000..b154c7f8 --- /dev/null +++ b/assets/icons/enquiry/phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index 00f2c6a0..674dc32a 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -306,6 +306,7 @@ import 'package:uae_stat/presentation/Screens/charts/chart.dart'; import 'package:uae_stat/presentation/Screens/charts/screens/chart_screen.dart'; import 'package:uae_stat/presentation/Screens/demo_home2.dart'; import 'package:uae_stat/presentation/Screens/online_offline_verification/internet_check.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/contactUs.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/notification/notification.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/AboutTheApp/AboutFCSC.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/AboutTheApp/getStarted.dart'; @@ -631,5 +632,10 @@ final GoRouter router = GoRouter( path: '/marriages', builder: (context, state) => Marriages(), ), + + GoRoute( + path: '/contact', + builder: (context, state) => Contact(), + ), ], ); diff --git a/lib/infrastructure/services/img_asset_paths/icons/enquiry_asset_icon_path.dart b/lib/infrastructure/services/img_asset_paths/icons/enquiry_asset_icon_path.dart new file mode 100644 index 00000000..e1219710 --- /dev/null +++ b/lib/infrastructure/services/img_asset_paths/icons/enquiry_asset_icon_path.dart @@ -0,0 +1,8 @@ +abstract class EnquiryAssetIconPath { + static const _basePath = 'assets/icons/enquiry'; + static const at = '$_basePath/at.svg'; + static const building = '$_basePath/building.svg'; + static const fax = '$_basePath/fax.svg'; + static const map = '$_basePath/map.svg'; + static const phone = '$_basePath/phone.svg'; +} \ No newline at end of file diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/contactUs.dart b/lib/presentation/routes/drawer_routes/Drawer Items/contactUs.dart new file mode 100644 index 00000000..bc8cb507 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/contactUs.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:uae_stat/domain/use_cases/language.dart'; +import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/enquiry_asset_icon_path.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +class Contact extends StatefulWidget { + const Contact({super.key}); + + @override + State createState() => _ContactState(); +} + +class _ContactState extends State { + @override + Widget build(BuildContext context) { + final double screenWidth= MediaQuery.of(context).size.width; + final double screenHeight= MediaQuery.of(context).size.height; + + + return BaseScaffold( + body: Container( + color: Colors.grey[200], + width: screenWidth, + padding: EdgeInsets.all(16.0), + child: SingleChildScrollView( + child: Column( + children: [ + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4.0), // Slight curve + ), + padding: EdgeInsets.all(7.0), + height: screenHeight*0.35, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(context.translate('DUBAI - EMIRATES TOWER -32ND FLOOR','دبي - أبراج الإمارات - الطابق 32'), + style: TextStyle( + color: Color(0xFF265E84), + fontSize: 20, + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + ), + ), + buildTextRow(EnquiryAssetIconPath.building,context.translate('Office : Dubai - Emirates Tower -32nd Floor','المقر الرئيسي : دبي - أبراج الإمارات - الطابق 32')), + buildTextRow(EnquiryAssetIconPath.phone,context.translate('Tel : 00971 46080000','الهاتف : 0097146080000'),), + buildTextRow(EnquiryAssetIconPath.fax, context.translate('Fax : 0097143273535','فاكس : 0097143273535')), + buildTextRow(EnquiryAssetIconPath.map, context.translate('P.O.Box : 127000 Dubai','ص.ب: : 127000 دبي')), + buildTextRow(EnquiryAssetIconPath.at, context.translate('Email Address : info@fcsc.gov.ae','البريد الإلكتروني : info@fcsc.gov.ae')), + buildTextRow(EnquiryAssetIconPath.map,context.translate( 'Latitude : 25.223926','خط العرض : 25.223926')), + buildTextRow(EnquiryAssetIconPath.map, context.translate('Longitude : 55.350526','خط الطول : 55.350526')), + ], + ), + ), + SizedBox(height: 10,), + Container( + padding: EdgeInsets.all(7.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4.0), // Slight curve + ), + height: screenHeight*0.34, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(context.translate('MEDIA SECTION','قسم الاعلام'), + style: TextStyle( + color: Color(0xFF265E84), + fontSize: 20, + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + ), + ), + buildTextRow(EnquiryAssetIconPath.building,context.translate('Office : Media Section','المقر الرئيسي : قسم الاعلام')), + buildTextRow(EnquiryAssetIconPath.phone,context.translate('Tel : 00971 46080000','الهاتف : 0097146080000'),), + buildTextRow(EnquiryAssetIconPath.fax, context.translate('Fax : 0097143273535','فاكس : 0097143273535')), + buildTextRow(EnquiryAssetIconPath.map, context.translate('P.O.Box : 127000 Dubai','ص.ب: : 127000 دبي')), + buildTextRow(EnquiryAssetIconPath.at, context.translate('Email Address : GCO@fcsc.gov.ae','البريد الإلكتروني : GCO@fcsc.gov.ae')), + buildTextRow(EnquiryAssetIconPath.map,context.translate( 'Latitude : 25.223926','خط العرض : 25.223926')), + buildTextRow(EnquiryAssetIconPath.map, context.translate('Longitude : 55.350526','خط الطول : 55.350526')), + ], + ), + ), + SizedBox(height: 10,), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4.0), // Slight curve + ), + padding: EdgeInsets.all(7.0), + height: screenHeight*0.34, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(context.translate('SGDS','أهداف التنمية المستدامة'), + style: TextStyle( + color: Color(0xFF265E84), + fontSize: 20, + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + ), + ), + buildTextRow(EnquiryAssetIconPath.building,context.translate('Office : SDGs','المقر الرئيسي : أهداف التنمية المستدامة')), + buildTextRow(EnquiryAssetIconPath.phone,context.translate('Tel : 00971 46080000','الهاتف : 0097146080000'),), + buildTextRow(EnquiryAssetIconPath.fax, context.translate('Fax : 0097143273535','فاكس : 0097143273535')), + buildTextRow(EnquiryAssetIconPath.map, context.translate('P.O.Box : 127000 Dubai','ص.ب: : 127000 دبي')), + buildTextRow(EnquiryAssetIconPath.at, context.translate('Email Address : sdgs@fcsc.gov.ae','البريد الإلكتروني : sdgs@fcsc.gov.ae')), + buildTextRow(EnquiryAssetIconPath.map,context.translate( 'Latitude : 25.223926','خط العرض : 25.223926')), + buildTextRow(EnquiryAssetIconPath.map, context.translate('Longitude : 55.350526','خط الطول : 55.350526')), + ], + ), + ), + ], + ), + ), + ), title: Text(context.translate('Contact Us','اتصل بنا')),); + } + + Widget buildTextRow(String iconName, String text) { + return Padding( + padding: const EdgeInsets.only(top:8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SvgPicture.asset( + iconName, + semanticsLabel: 'Filter', + width: 24, + height: 24, + ), + SizedBox(width: 8), // Add spacing if needed + Text( + text, // Dynamic text + style: TextStyle( + fontSize: 16, + color: Color(0xFF878787), + ), + ), + ], + ), + ); + } + +} diff --git a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart index 322e04bc..be6ba665 100644 --- a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart +++ b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart @@ -974,6 +974,11 @@ class _BaseScaffoldState extends ConsumerState { title: Text(AppLocalizations.of(context)!.guide_title), onTap: () => _navigateTo(context, '/user-guide'), ), + ListTile( + leading: Icon(Icons.phone), + title: const Text('Contact'), + onTap: () => context.push('/contact'), + ), if (userId != 'guest') ListTile( leading: Icon(Icons.logout), diff --git a/pubspec.yaml b/pubspec.yaml index 4248f8ff..c6b6c97f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -139,6 +139,7 @@ flutter: - assets/icons/misc/group.png - assets/icons/misc/search.png - assets/icons/bookmark/ + - assets/icons/enquiry/ fonts: - family: Segoe