From 74196e1d1a5744180cc20296f7d61f6cde7be8a2 Mon Sep 17 00:00:00 2001 From: Juki-shiba Date: Mon, 3 Mar 2025 14:45:06 +0530 Subject: [PATCH] Saving local changes before pulling --- .../Screens/charts/screens/chart_screen.dart | 1243 +++++++---------- 1 file changed, 527 insertions(+), 716 deletions(-) diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index d3021464..8f73b70f 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -10,7 +8,6 @@ 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'; @@ -21,7 +18,6 @@ import 'package:uae_stat/presentation/components/my_toggle.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; -import 'package:url_launcher/url_launcher.dart'; import '../filters/search_filter_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -35,8 +31,6 @@ 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, @@ -45,21 +39,17 @@ 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(apiUrl); + final _pb = PocketBase('https://pb.venbait.in'); List> selectedFiltersStorage = []; final GlobalKey _scaffoldKey = GlobalKey(); final ApiService apiService = ApiService(); bool isLoading = true; - bool _isSharing = false; List isChartData = []; List nonChartData = []; Map chartScreenData = {}; @@ -77,9 +67,6 @@ class _ChartScreen1State extends ConsumerState { late Color backgroundColor; final ScrollController _scrollController = ScrollController(); int _activeTabIndex = 0; - dynamic tabWiseKpi=[]; - dynamic tabFilteredKpi=[]; - List> formattedFilters=[]; dynamic _tabsData = []; // List> _tabsData = []; @@ -98,12 +85,11 @@ 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', widget.kpi, widget.filter_data) - .then((_) { - if(_tabsData.isNotEmpty) { + fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) { + if (_tabsData.isNotEmpty) { // Call onTabSelected for the first tab onTabSelected(_tabsData[0]['id']); } @@ -173,7 +159,10 @@ 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), ), ); @@ -184,10 +173,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), ), ); @@ -216,7 +205,10 @@ 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), ), ); @@ -227,10 +219,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), ), ); @@ -278,55 +270,49 @@ class _ChartScreen1State extends ConsumerState { ), actions: [ SizedBox(height: 20), - 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, - ), - ), + 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 ), ), - 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), - ), + 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), + ), + ), + ), ], ), ); @@ -371,51 +357,48 @@ class _ChartScreen1State extends ConsumerState { ), actions: [ SizedBox(height: 20), - 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 - ), + 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 ), - child: Text( - context.translate('No', 'لا'), - style: TextStyle( - color: Color(0xFFAA8E83), - fontSize: 16, - ), + 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, ), ), ), - 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), - ), + ), + 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), + ), + ), ), ], ), @@ -1219,8 +1202,6 @@ class _ChartScreen1State extends ConsumerState { // } void processChartData(chartsData) { - print("PROCESSING FILTER CHART DATa"); - // Group data by 'kpi' Map>> groupedData = {}; @@ -1250,6 +1231,7 @@ 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(); @@ -1262,7 +1244,7 @@ class _ChartScreen1State extends ConsumerState { print('Sorted Tabs: $_tabs'); - // print('Grouped Data: $groupedData'); + print('Grouped Data: $groupedData'); print('Tabs: $_tabs'); setState(() { @@ -1270,13 +1252,8 @@ class _ChartScreen1State extends ConsumerState { }); } - 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'); - + Future fetchChartData(String dataSets, locale) async { + var data = await apiService.fetchChartData(dataSets, locale); if (data.containsKey('filterData')) { var filterData = data['filterData']; @@ -1304,71 +1281,18 @@ 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"); @@ -1505,9 +1429,6 @@ 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 @@ -1516,8 +1437,6 @@ 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, @@ -1540,12 +1459,11 @@ class _ChartScreen1State extends ConsumerState { children: [ Row( children: [ - SvgPicture.asset( - UaeNumbersAssetPath.filterCharts, - semanticsLabel: 'Filter', - colorFilter:ColorFilter.mode(Color(0xFF8E8E8E),BlendMode.srcIn), - width: 25, - height: 25, + Image.asset( + UaeNumbersAssetPath.filterUae, + color: Color(0xFF8E8E8E), // Outline color + width: 24, // Slightly larger + height: 24, ), SizedBox(width: 8), Text( @@ -1788,13 +1706,6 @@ 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( @@ -1827,7 +1738,6 @@ class _ChartScreen1State extends ConsumerState { onPressed: () { print( "Selected Filters before applying: $selectedFilters"); - setState(() { chartsData = originalTabChartsData; cardData = originalTabCardData; @@ -1835,7 +1745,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), @@ -1877,10 +1787,8 @@ class _ChartScreen1State extends ConsumerState { } void onTabSelected(String tabId) { - print('Selected Tab on: $tabId'); - tabWiseKpi = tabId; - - // selectedFiltersStorage.clear(); + print('Selected Tab: $tabId'); + selectedFiltersStorage.clear(); // Filter the filterDataSet filterData = filterDataSet .where((item) => item['key'] == tabId) @@ -1916,8 +1824,7 @@ class _ChartScreen1State extends ConsumerState { } void performActionForTab(String tabId) { - - print('Selected Tab perform: $tabId'); + print('Selected Tab: $tabId'); // Filter the chartsData array based on the tabId tabFilteredChartData = chartsData.where((chart) { @@ -2013,18 +1920,12 @@ class _ChartScreen1State extends ConsumerState { final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null // fetchChartData(widget.dataSets, localeCode); - - final List> safeFilterData = widget.filter_data ?? []; - final String safeKpi = widget.kpi ?? ''; - fetchChartData(widget.dataSets,localeCode, safeKpi, safeFilterData).then((_) { - print('DEBUG KPI: $safeKpi'); + fetchChartData(widget.dataSets, localeCode).then((_) { 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; @@ -2222,29 +2123,28 @@ class _ChartScreen1State extends ConsumerState { ], ), SizedBox(width: 10), - GestureDetector( - onTap: () => shareCurrentPage(context, _isSharing), - child: Row( - children: [ - Text( - context.translate( - 'Share', - 'يشارك', - ), - style: const TextStyle( - fontSize: 16, - color: Colors.white, - ), + Row( + children: [ + Text( + context.translate( + 'Share', + 'يشارك', ), - SizedBox(width: 5), - SvgPicture.asset( - UaeNumbersAssetPath.share, - semanticsLabel: 'share', - width: 24, - height: 24, + style: const TextStyle( + fontSize: 16, + color: Colors.white, ), - ], - ), + ), + SizedBox(width: 5), + GestureDetector( + onTap: () => shareCurrentPage(context), + child: SvgPicture.asset( + UaeNumbersAssetPath.share, + semanticsLabel: 'share', + width: 24, + height: 24, + )), + ], ), SizedBox( width: 10), // Horizontal space between items @@ -2268,11 +2168,12 @@ class _ChartScreen1State extends ConsumerState { ), ), SizedBox(width: 10), - SvgPicture.asset( - UaeNumbersAssetPath.filterCharts, - semanticsLabel: 'Filter', - width: 24, - height: 24, + Image.asset( + UaeNumbersAssetPath.filterUae, + color: Colors + .white, // Set color to white + width: 21, + height: 21, ), ], ), @@ -2352,484 +2253,399 @@ class _ChartScreen1State extends ConsumerState { // ), // nonChartData Cards Padding( - padding: const EdgeInsets.all(8.0), - child: LayoutBuilder( - builder: (context, constraints) { - List rows = []; - List tempRow = []; + 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, - 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 = []; - } - } + 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 (tempRow.isNotEmpty) { - rows.add(Row(children: tempRow)); - } - - return SingleChildScrollView( - child: Column( - children: rows, - ), - ); - }, - ), - ), - ListView.builder( - itemCount: chartsData.length, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return Card( - margin: const EdgeInsets.all(10), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Color( - int.parse( - (chartScreenData[ - 'border_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, + 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 ), - ), // Border color - width: 1, // Border width - ), - color: Colors.white, - borderRadius: BorderRadius.circular( - 8), // Optional: Rounded corners - ), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - // ConstrainedBox - Container( - height: (chartsData[index] - ['chart_type'] == - 'pie_chart') - ? 500 - : (chartsData[index][ - 'chart_type'] == - 'bar_chart_horizontal') - ? 370 - : (chartsData[index]['chart_type'] == 'fl_stacked_bar') - ? 390 - : 350, - - // child: buildChart(chartsData[index]), - child: ChartWidget( - chartData: - chartsData[index], - bodyColor: bodyColor)) - ], + 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 - Widget _buildArrowButton( - {required VoidCallback? onPressed, required IconData icon}) { - final color = - Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16)); - return Container( - margin: EdgeInsets.symmetric(horizontal: 5.0), - width: 30.0, // Set the width of the circle - height: 30.0, - decoration: BoxDecoration( - color: onPressed == null ? Colors.grey[400] : Colors.white, - shape: BoxShape.circle, - // boxShadow: [ - // BoxShadow( - // color: Colors.black26, - // blurRadius: 4.0, - // offset: Offset(2, 2), - // ), - // ], - ), - child: IconButton( - onPressed: onPressed, - icon: Icon(icon, color: onPressed == null ? Colors.grey : color), - iconSize: 15.0, - ), - ); - } + 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'})', - Widget _buildTab(Map tab, {bool isActive = false}) { - return GestureDetector( - onTap: () { - setState(() { - _activeTabIndex = _tabsData.indexOf(tab); - }); - _scrollToIndex(_activeTabIndex); - onTabSelected(tab['id']!); - }, - child: Container( - margin: EdgeInsets.symmetric(horizontal: 8.0), - padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 16.0), - decoration: BoxDecoration( - color: isActive ? Colors.white : Colors.grey[400], - borderRadius: BorderRadius.circular(20.0), - ), - child: Text( - tab['name']!, - style: TextStyle( - color: isActive ? Colors.black : Colors.white, - fontWeight: isActive ? FontWeight.w500 : FontWeight.w400, - fontSize: 13, - ), - ), - ), - ); - } -} - -Future shareCurrentPage(BuildContext context) async { - try { - // Get current route from go_router - final String currentRoute = GoRouterState.of(context).uri.toString(); - final String baseAppLink = 'https://fcsc-da580.web.app'; - final String shareLink = '$baseAppLink$currentRoute'; - final String shareText = 'Check this out!'; - final String svgAssetPath = 'assets/logos/fcsc.png'; - - final screenshotController = ScreenshotController(); - final svgWidget = SvgPicture.asset( - svgAssetPath, - width: 200, - height: 200, - ); - final Uint8List? capturedImage = - await screenshotController.captureFromWidget( - Material(child: svgWidget), - ); - - if (capturedImage == null) { - throw Exception('Failed to capture SVG as image'); - } - - final directory = await getTemporaryDirectory(); - final file = File('${directory.path}/shared_image.png'); - await file.writeAsBytes(capturedImage); - - await Share.shareXFiles( - [XFile(file.path)], - text: '$shareText\n$shareLink', - subject: 'Shared Content', - ); - - await file.delete(); - } catch (e) { - print("Error sharing file: $e"); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error sharing: $e')), - ); - } -} - -// Function to convert hex color string to Color -Color _getColorFromHex(String hexColor) { - hexColor = hexColor.replaceFirst('#', ''); - if (hexColor.length == 6) { - hexColor = 'FF$hexColor'; // Add alpha if not provided - } - return Color(int.parse(hexColor, radix: 16)); -} - -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.isEmpty) - { - return SizedBox.shrink(); - } - else 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'}', + RegExp(r'\d').hasMatch(response[ + 0][ + 'display_value'] ?? + '') + ? '(${response[0]['display_value'] ?? 'NA'})' + : '${response[0]['display_value'] ?? 'NA'}', style: const TextStyle( fontSize: 11, @@ -3034,17 +2850,14 @@ class CardWidget extends StatelessWidget { } } -Future shareCurrentPage(BuildContext context, bool _isSharing) async { - if (_isSharing) return; // Prevent multiple taps - - _isSharing = true; - +Future shareCurrentPage(BuildContext context) async { try { + // Get current route from go_router final String currentRoute = GoRouterState.of(context).uri.toString(); final String baseAppLink = 'https://fcsc-da580.web.app'; final String shareLink = '$baseAppLink$currentRoute'; final String shareText = 'Check this out!'; - final String svgAssetPath = 'assets/backgrounds/share/fcsc.svg'; + final String svgAssetPath = 'assets/logos/fcsc.png'; final screenshotController = ScreenshotController(); final svgWidget = SvgPicture.asset( @@ -3052,8 +2865,8 @@ Future shareCurrentPage(BuildContext context, bool _isSharing) async { width: 200, height: 200, ); - - final Uint8List? capturedImage = await screenshotController.captureFromWidget( + final Uint8List? capturedImage = + await screenshotController.captureFromWidget( Material(child: svgWidget), ); @@ -3062,7 +2875,7 @@ Future shareCurrentPage(BuildContext context, bool _isSharing) async { } final directory = await getTemporaryDirectory(); - final file = File('${directory.path}/share.svg'); + final file = File('${directory.path}/shared_image.png'); await file.writeAsBytes(capturedImage); await Share.shareXFiles( @@ -3075,10 +2888,8 @@ Future shareCurrentPage(BuildContext context, bool _isSharing) async { } catch (e) { print("Error sharing file: $e"); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), + SnackBar(content: Text('Error sharing: $e')), ); - } finally { - _isSharing = false; // Reset flag after sharing completes } }