From f6c14eb2e55c44854edba0c33e746d3b6277d1c3 Mon Sep 17 00:00:00 2001 From: SurendarSuri30 Date: Thu, 12 Jun 2025 11:45:26 +0530 Subject: [PATCH 1/2] bhavin feedback changes --- .../Screens/charts/screens/chart_screen.dart | 8 +- .../Screens/charts/widgets/chart_widget.dart | 786 ++++++++++++++---- .../components/constant/constant.dart | 2 +- .../tab_routes/home_route.dart | 2 +- 4 files changed, 615 insertions(+), 183 deletions(-) diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index 19b5169c..379f1e93 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1462,6 +1462,10 @@ class _ChartScreen1State extends ConsumerState { void applyFilters(BuildContext context, List filters, List data, List dataCard, List selectedFilters) { + setState(() { + isLoading = true; + }); + Navigator.pop(context); print('applyFilters called'); print('Selected ApplyFilters: $selectedFilters'); @@ -1505,7 +1509,7 @@ class _ChartScreen1State extends ConsumerState { tabWiseKpi, // Ensure you are passing the correct KPI here formattedFilters // Pass the formatted filter data here ); - Navigator.pop(context); + // Navigator.pop(context); selectedFiltersStorage = List.from(selectedFilters); print('selectedFiltersStoraged- $selectedFiltersStorage'); @@ -1999,7 +2003,7 @@ class _ChartScreen1State extends ConsumerState { Navigator.pop(context); } else { setState(() { - isLoading = true; + // isLoading = true; chartsData = originalTabChartsData; cardData = originalTabCardData; }); diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index d8cd40b8..1e1cb772 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -90,20 +90,28 @@ class ChartWidget extends StatelessWidget { // Function to get colors for both English & Arabic keys List get uniqueColors { final Map translations = { - 'الاقتصاد': 'ECONOMY', - 'الاجتماعي': 'SOCIAL', - 'البيئة': 'ENVIRONMENT', + 'اقتصاد': 'ECONOMY', + 'اجتماعي': 'SOCIAL', + 'بيئة': 'ENVIRONMENT', }; + print('color check'); + print(translations); + print('chartHeader $chartHeader'); + print(translations[chartHeader]); + + String key = translations[chartHeader] ?? chartHeader; + print(key); + print(colorMap[key]); return colorMap[key] ?? [Colors.grey]; } List get uniqueColorsForTwo { final Map translations = { - 'الاقتصاد': 'ECONOMY', - 'الاجتماعي': 'SOCIAL', - 'البيئة': 'ENVIRONMENT', + 'اقتصاد': 'ECONOMY', + 'اجتماعي': 'SOCIAL', + 'بيئة': 'ENVIRONMENT', }; String key = translations[chartHeader] ?? chartHeader; @@ -112,9 +120,9 @@ class ChartWidget extends StatelessWidget { List get uniqueColorsForThree { final Map translations = { - 'الاقتصاد': 'ECONOMY', - 'الاجتماعي': 'SOCIAL', - 'البيئة': 'ENVIRONMENT', + 'اقتصاد': 'ECONOMY', + 'اجتماعي': 'SOCIAL', + 'بيئة': 'ENVIRONMENT', }; String key = translations[chartHeader] ?? chartHeader; @@ -1271,12 +1279,7 @@ class ChartWidget extends StatelessWidget { Set selectedYears = {1970, 1980, 1990, 2000, 2010, 2020}; Map groupColorMap = {}; int colorIndex = 0; - // for (String group in groupByValues) { - // // groupColorMap[group] = uniqueColors[colorIndex % uniqueColors.length]; - // groupColorMap[group] = uniqueColorsLine_trend_2[ - // colorIndex % uniqueColorsLine_trend_2.length]; - // colorIndex++; - // } + // Extract all years from the chart data List years = (chartData['response'] as List) @@ -1322,16 +1325,7 @@ class ChartWidget extends StatelessWidget { barColorsMap[key] = value.toString(); // Ensure values are strings }); bool hasBarColors = barColorsMap.isNotEmpty; - // var chartBarColorsRaw = chartData['chart_bar_color'] ?? {}; - // // Convert LinkedMap to Map - // Map chartBarColrs = - // Map.from(chartBarColorsRaw); - // // Now map to Color - // Map parsedChartBarColors = - // chartBarColrs.map((key, value) { - // return MapEntry(key, _hexToColor(value)); - // }); - // + List keys = chartBarColors['key'] ?? []; List colors = chartBarColors['color'] ?? []; @@ -1359,109 +1353,288 @@ class ChartWidget extends StatelessWidget { colorIndex++; } - // Generate line bars for the chart - List lineBars = lineBarsData( - filteredData, - groupByValues, - groupByKey, - parsedChartBarColors, - ); - return Column( - children: [ - Text( - chartData['chart_heading'] ?? '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 14, fontWeight: FontWeight.w400), - textAlign: TextAlign.center, - ), - SizedBox(height: 5), - Text( - chartData['chart_sub_heading'] ?? '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 13, fontWeight: FontWeight.w300), - textAlign: TextAlign.center, - ), - SizedBox(height: 10), - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Enable horizontal scrolling - padding: const EdgeInsets.only(right: 40, top: 10), - child: SizedBox( - width: (uniqueXValues.length * 50) + - 50, // Adjust width dynamically - child: LineChart( - LineChartData( - lineTouchData: lineTouchData1(context), - gridData: gridData(), - titlesData: titlesData1(uniqueXValues,context), - borderData: borderData(), - lineBarsData: lineBars, - minX: uniqueXValues.reduce((a, b) => a < b ? a : b), - maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), - ), - ), + + + final Map>> groupedData = {}; + +// Step 1: Group data by PLANT_TYPE + for (var item in filteredData) { + final plantType = item['ObsKey'][groupByKey]; + groupedData.putIfAbsent(plantType, () => []).add(item); + } + +// Step 2: Convert grouped data into List + final List lineBars = []; + final List colorPalette = [ + Color(0xFF6097CD), + Color(0xFFD086A7), + Color(0xFF98BCE5), + Color(0xFFA7B5C5), + Color(0xFFBED3EC), + Color(0xFFD4E3F4), + ]; + + String formatNumber(double value) { + if (value >= 1e12) { + return '${(value / 1e12).toStringAsFixed(2)}T'; + } else if (value >= 1e9) { + return '${(value / 1e9).toStringAsFixed(2)}B'; + } else if (value >= 1e6) { + return '${(value / 1e6).toStringAsFixed(2)}M'; + } else if (value >= 1e3) { + return '${(value / 1e3).toStringAsFixed(2)}K'; + } else { + return value.toStringAsFixed(2); // No decimals for small numbers + } + } + + final getXValue = chartData['chart_type_json']['x'] ?? ''; + groupedData.forEach((plantType, entries) { + final spots = entries.map((entry) { + final year = double.tryParse(entry['ObsKey'][getXValue].toString()) ?? 0; + final value = double.tryParse(entry['ObsValue']['Value'].toString()) ?? 0; + return FlSpot(year, value); + }).toList() + ..sort((a, b) => a.x.compareTo(b.x)); // Sort by year + final baseColor = groupColorMap[plantType] ?? Colors.grey; + lineBars.add( + LineChartBarData( + spots: spots, + isCurved: true, + barWidth: 3, + // color: groupColorMap[plantType] ?? Colors.grey, + color: baseColor.withOpacity(0.9), + dotData: FlDotData(show: true), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + // baseColor.withOpacity(0.2), // visible base color + // Colors.white, // fade to white + baseColor.withOpacity(0.4), // increase opacity + baseColor.withOpacity(0.0), // fade to transparent (not white) + ], + stops: [ + 0.2, // shift teal color start downward (20% from the top) + 1.0, // white at the bottom + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, ), ), + showingIndicators: List.generate(spots.length, (index) => index), + ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Wrap( - spacing: 12, - runSpacing: 8, - children: groupByValues.map((group) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 12, - height: 12, - color: groupColorMap[group], + ); + colorIndex++; + }); + + return Scaffold( + backgroundColor: Colors.white, + body: Padding( + padding: const EdgeInsets.all(10), + child: LayoutBuilder( + builder: (context, constraints) { + final chartWidth = constraints.maxWidth; + final chartHeight = constraints.maxHeight; + final allSpots = lineBars.expand((line) => line.spots); + final minY = allSpots.map((e) => e.y).reduce((a, b) => a < b ? a : b); + final maxY = allSpots.map((e) => e.y).reduce((a, b) => a > b ? a : b); + + + final xValues = allSpots.map((e) => e.x).toList(); + final minX = xValues.reduce((a, b) => a < b ? a : b).toInt(); + final maxX = xValues.reduce((a, b) => a > b ? a : b).toInt(); + + final paddingFactor = 0.3; // 10% extra padding + + final chartMinY = minY - (maxY - minY) * paddingFactor; + final chartMaxY = maxY + (maxY - minY) * paddingFactor; + + + return Column( + crossAxisAlignment: CrossAxisAlignment.center, // ensures center alignment + children: [ + Padding( + padding: const EdgeInsets.only(top: 0), + child: Text( + chartData['chart_heading'] ?? 'Production Quantity by Crop Type (Metric Tonne)', + style: TextStyle( + fontFamily: context.translate('Roboto', 'NotoKufi'), + fontSize: 14, + fontWeight: FontWeight.w400, + ), + textAlign: TextAlign.center, ), - SizedBox(width: 6), - Text(group, style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 14)), - ], - ); - }).toList(), - ), + ), + // SizedBox(height: 6), + Expanded( + child: Stack( + children: [ + LineChart( + LineChartData( + minY: chartMinY, + maxY: chartMaxY, + lineBarsData: lineBars, + clipData: FlClipData.all(), // make sure this doesn't clip the left side + + // Add space for tooltip/dot + // extraLeftTitlesReservedWidth: 24, + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.black, + fontSize: 10, + ); + + // Show only for full years + if (selectedYears.contains(value.toInt())) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Top tick mark (simulated using a container) + Container( + width: 1, + height: 8, + color: Colors.black, + margin: EdgeInsets.only(bottom: 2), + ), + Text(value.toInt().toString(), style: style), + ], + ); + } + return const SizedBox.shrink(); + }, + reservedSize: 30, + interval: 1, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + // interval: 5, + reservedSize: 90, + getTitlesWidget: (value, _) => + Text('${value.toInt()}', style: TextStyle(fontSize: 12)), + ), + ), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + borderData: FlBorderData( + show: true, + border: const Border( + left: BorderSide.none, + bottom: BorderSide(color: Colors.black), + ), + ), + gridData: FlGridData(show: false), + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + // tooltipBgColor: Colors.black.withOpacity(0.7), + fitInsideHorizontally: true, + fitInsideVertically: true, + getTooltipItems: (spots) { + return spots.map((spot) { + final x = spot.x.toInt(); + // if (x == minX || x == maxX) return null; + return LineTooltipItem( + formatNumber(spot.y), + const TextStyle(color: Colors.white), + ); + }).toList(); + }, + ), + ), + ), + ), + + ...lineBars.expand((barData) { + final List spots = barData.spots; + final color = barData.color ?? Colors.black; + + return spots.map((spot) { + final xPos = ((spot.x - minX) / (maxX - minX)) * chartWidth; + final yPos = (1 - (spot.y - chartMinY) / (chartMaxY - chartMinY)) * chartHeight; + // Prevent label from going outside on the left + double adjustedLeft = math.max(0, xPos - 30); + return Stack( + children: [ + Positioned( + left: adjustedLeft, // fine-tune horizontal position + top: yPos - 60, // fine-tune vertical position + child: Text( + formatNumber(spot.y), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 9, + fontWeight: FontWeight.w500, + // color: color, + color: Colors.black, + ), + ), + ) + ] + ); + + }); + }).toList(), + + ], + ), + ), + SizedBox(height: 12), + Wrap( // <-- Legend added here + spacing: 12, + runSpacing: 8, + children: groupByValues.map((group) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container(width: 12, height: 12, color: groupColorMap[group]), + SizedBox(width: 6), + Text( + group, + style: TextStyle( + fontSize: 14, + fontFamily: context.translate('Roboto', 'NotoKufi'), + ), + ), + ], + ); + }).toList(), + ), + ], + ); + + + + }, ), - // Chart - ], + ), ); case 'line_trend_2': - // final List uniqueColorsLine_trend_2 = [ - // Color(0xFF6097CD), - // Color(0xFFD086A7), - // Color(0xFF98BCE5), - // Color(0xFFA7B5C5), - // Color(0xFFBED3EC), - // Color(0xFFD4E3F4), - // ]; + final List uniqueColorsLine_trend_2 = [ + Color(0xFF6097CD), + Color(0xFFD086A7), + ]; Set selectedYears = {1970, 1980, 1990, 2000, 2010, 2020}; Map groupColorMap = {}; int colorIndex = 0; - // for (String group in groupByValues) { - // // groupColorMap[group] = uniqueColorsLine_trend_2[ - // // colorIndex % uniqueColorsLine_trend_2.length]; - // groupColorMap[group] = uniqueColors[colorIndex % uniqueColors.length]; - // // groupColorMap[group] = adjustColorlineTrend(bodyColor, colorIndex); - // colorIndex++; - // } + // Extract all years from the chart data List years = (chartData['response'] as List) .map( (entry) => - int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, - ) + int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, + ) .toList(); if (years.isEmpty) { @@ -1482,7 +1655,7 @@ class ChartWidget extends StatelessWidget { // Filter chart data to include only the selected years List filteredData = - (chartData['response'] as List).where((entry) { + (chartData['response'] as List).where((entry) { int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; return selectedYears.contains(year); }).toList(); @@ -1490,91 +1663,344 @@ class ChartWidget extends StatelessWidget { Set uniqueXValues = filteredData .map( (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), - ) + ) .toSet(); - print('uniqueXValuesLineTrend2- $uniqueXValues'); - var chartBarColors = chartData['chart_bar_color'] ?? {}; Map barColorsMap = {}; + chartBarColors.forEach((key, value) { barColorsMap[key] = value.toString(); // Ensure values are strings }); bool hasBarColors = barColorsMap.isNotEmpty; - var chartBarColorsRaw = chartData['chart_bar_color'] ?? {}; - // Convert LinkedMap to Map - Map chartBarColrs = Map.from( - chartBarColorsRaw, - ); + List keys = chartBarColors['key'] ?? []; + List colors = chartBarColors['color'] ?? []; - // Now map to Color - Map parsedChartBarColors = chartBarColrs.map(( - key, - value, - ) { - return MapEntry(key, _hexToColor(value)); - }); + print('RT1keys - $keys'); + print('RT1colors - $colors'); + + // Convert to a map for easy lookup + Map parsedChartBarColors = {}; + for (int i = 0; i < keys.length; i++) { + parsedChartBarColors[keys[i].toString()] = _hexToColor( + colors[i].toString(), + ); + } + print('RTLinr1 - $parsedChartBarColors'); for (String group in groupByValues) { if (parsedChartBarColors.containsKey(group)) { groupColorMap[group] = - parsedChartBarColors[group]!; // Directly assign as Color + parsedChartBarColors[group]!; // Directly assign as Color } else { groupColorMap[group] = - uniqueColors[colorIndex % uniqueColors.length]; + uniqueColors[colorIndex % uniqueColors.length]; } colorIndex++; } - // Generate line bars for the chart - List lineBars = lineBarsData2(filteredData); - return Column( - children: [ - Text( - chartData['chart_heading'] ?? '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 14, fontWeight: FontWeight.w400), - textAlign: TextAlign.center, - ), - SizedBox(height: 5), - Text( - '', - style: TextStyle(fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ),fontSize: 13, fontWeight: FontWeight.w300), - textAlign: TextAlign.center, - ), - SizedBox(height: 10), - // Chart - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, // Enable horizontal scrolling - padding: const EdgeInsets.only(right: 40, top: 20), - child: SizedBox( - width: (uniqueXValues.length * 50) + - 50, // Adjust width dynamically - child: LineChart( - LineChartData( - lineTouchData: lineTouchData1(context), - gridData: gridData(), - titlesData: titlesData1(uniqueXValues,context), - borderData: borderData(), - lineBarsData: lineBars, - minX: uniqueXValues.reduce((a, b) => a < b ? a : b), - maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), - minY: 0, - ), - ), + + + + final Map>> groupedData = {}; + +// Step 1: Group data by PLANT_TYPE + for (var item in filteredData) { + final plantType = item['ObsKey'][groupByKey]; + groupedData.putIfAbsent(plantType, () => []).add(item); + } + +// Step 2: Convert grouped data into List + final List lineBars = []; + final List colorPalette = [ + Color(0xFF6097CD), + Color(0xFFD086A7), + Color(0xFF98BCE5), + Color(0xFFA7B5C5), + Color(0xFFBED3EC), + Color(0xFFD4E3F4), + ]; + + String formatNumber(double value) { + if (value >= 1e12) { + return '${(value / 1e12).toStringAsFixed(2)}T'; + } else if (value >= 1e9) { + return '${(value / 1e9).toStringAsFixed(2)}B'; + } else if (value >= 1e6) { + return '${(value / 1e6).toStringAsFixed(2)}M'; + } else if (value >= 1e3) { + return '${(value / 1e3).toStringAsFixed(2)}K'; + } else { + return value.toStringAsFixed(2); // No decimals for small numbers + } + } + + final getXValue = chartData['chart_type_json']['x'] ?? ''; + groupedData.forEach((plantType, entries) { + // Create a map to store population values by year and gender + Map> yearGenderMap = {}; + + for (var entry in filteredData) { + int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'].toString()) ?? 0; + String gender = entry['ObsKey']['GENDER']; + + double value = + double.tryParse(entry['ObsValue']['Value'].toString()) ?? 0.0; + + if (!yearGenderMap.containsKey(year)) { + yearGenderMap[year] = {'M': 0.0, 'F': 0.0}; + } + + if (gender == 'Male' || gender == 'ذكر') { + yearGenderMap[year]!['M'] = value; + } else if (gender == 'Female' || gender == 'أنثى') { + yearGenderMap[year]!['F'] = value; + } + } + + // Calculate the ratio (M/F) * 100 for each year + List spots = []; + yearGenderMap.forEach((year, genderMap) { + if (genderMap['M'] != 0.0 && genderMap['F'] != 0.0) { + double ratio = (genderMap['M']! / genderMap['F']!) * 100; + spots.add(FlSpot(year.toDouble(), ratio)); + } + }); + final baseColor = groupColorMap[plantType] ?? Colors.grey; + + lineBars.add( + LineChartBarData( + spots: spots, + isCurved: true, + barWidth: 3, + // color: groupColorMap[plantType] ?? Colors.grey, + color: baseColor.withOpacity(0.9), + dotData: FlDotData(show: true), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + // baseColor.withOpacity(0.2), // visible base color + // Colors.white, // fade to white + baseColor.withOpacity(0.4), // increase opacity + baseColor.withOpacity(0.0), // fade to transparent (not white) + ], + stops: [ + 0.2, // shift teal color start downward (20% from the top) + 1.0, // white at the bottom + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, ), ), + showingIndicators: List.generate(spots.length, (index) => index), + ), - ], + ); + colorIndex++; + }); + + return Scaffold( + backgroundColor: Colors.white, + body: Padding( + padding: const EdgeInsets.all(10), + child: LayoutBuilder( + builder: (context, constraints) { + final chartWidth = constraints.maxWidth; + final chartHeight = constraints.maxHeight; + final allSpots = lineBars.expand((line) => line.spots); + final minY = allSpots.map((e) => e.y).reduce((a, b) => a < b ? a : b); + final maxY = allSpots.map((e) => e.y).reduce((a, b) => a > b ? a : b); + + + final xValues = allSpots.map((e) => e.x).toList(); + final minX = xValues.reduce((a, b) => a < b ? a : b).toInt(); + final maxX = xValues.reduce((a, b) => a > b ? a : b).toInt(); + + final paddingFactor = 0.3; // 10% extra padding + + final chartMinY = minY - (maxY - minY) * paddingFactor; + final chartMaxY = maxY + (maxY - minY) * paddingFactor; + + + return Column( + crossAxisAlignment: CrossAxisAlignment.center, // ensures center alignment + children: [ + Padding( + padding: const EdgeInsets.only(top: 0), + child: Text( + chartData['chart_heading'] ?? 'Production Quantity by Crop Type (Metric Tonne)', + style: TextStyle( + fontFamily: context.translate('Roboto', 'NotoKufi'), + fontSize: 14, + fontWeight: FontWeight.w400, + ), + textAlign: TextAlign.center, + ), + ), + // SizedBox(height: 6), + Expanded( + child: Stack( + children: [ + LineChart( + LineChartData( + minY: chartMinY, + maxY: chartMaxY, + lineBarsData: lineBars, + clipData: FlClipData.all(), // make sure this doesn't clip the left side + + // Add space for tooltip/dot + // extraLeftTitlesReservedWidth: 24, + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, meta) { + const style = TextStyle( + color: Colors.black, + fontSize: 10, + ); + + // Show only for full years + if (selectedYears.contains(value.toInt())) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Top tick mark (simulated using a container) + Container( + width: 1, + height: 8, + color: Colors.black, + margin: EdgeInsets.only(bottom: 2), + ), + Text(value.toInt().toString(), style: style), + ], + ); + } + return const SizedBox.shrink(); + }, + reservedSize: 30, + interval: 1, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + // interval: 5, + reservedSize: 90, + getTitlesWidget: (value, _) => + Text('${value.toInt()}', style: TextStyle(fontSize: 12)), + ), + ), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + borderData: FlBorderData( + show: true, + border: const Border( + left: BorderSide.none, + bottom: BorderSide(color: Colors.black), + ), + ), + gridData: FlGridData(show: false), + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + // tooltipBgColor: Colors.black.withOpacity(0.7), + fitInsideHorizontally: true, + fitInsideVertically: true, + getTooltipItems: (spots) { + return spots.map((spot) { + final x = spot.x.toInt(); + // if (x == minX || x == maxX) return null; + // Use barIndex to determine which line this belongs to + final barIndex = spot.barIndex; + if (lineBars[barIndex].spots.isEmpty) return null; + + // Check the group name (plantType) from your groupedData order + final plantType = groupedData.keys.toList()[barIndex]; + print('plantType $plantType'); + + if (plantType != "Male" && plantType != "ذكر") { + return null; + } + return LineTooltipItem( + formatNumber(spot.y), + const TextStyle(color: Colors.white), + ); + }).toList(); + }, + ), + ), + ), + ), + + ...lineBars.expand((barData) { + final List spots = barData.spots; + final color = barData.color ?? Colors.black; + + return spots.map((spot) { + final xPos = ((spot.x - minX) / (maxX - minX)) * chartWidth; + final yPos = (1 - (spot.y - chartMinY) / (chartMaxY - chartMinY)) * chartHeight; + // Prevent label from going outside on the left + double adjustedLeft = math.max(0, xPos - 30); + return Stack( + children: [ + Positioned( + left: adjustedLeft, // fine-tune horizontal position + top: yPos - 70, // fine-tune vertical position + child: Text( + formatNumber(spot.y), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 9, + fontWeight: FontWeight.w500, + // color: color, + color: Colors.black, + ), + ), + ) + ] + ); + + }); + }).toList(), + + ], + ), + ), + SizedBox(height: 12), + // Wrap( // <-- Legend added here + // spacing: 12, + // runSpacing: 8, + // children: groupByValues.map((group) { + // return Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Container(width: 12, height: 12, color: groupColorMap[group]), + // SizedBox(width: 6), + // Text( + // group, + // style: TextStyle( + // fontSize: 14, + // fontFamily: context.translate('Roboto', 'NotoKufi'), + // ), + // ), + // ], + // ); + // }).toList(), + // ), + ], + ); + + + + }, + ), + ), ); case 'bar_chart': // Extract groupBy values and their corresponding y-axis values @@ -1720,7 +2146,7 @@ class ChartWidget extends StatelessWidget { child: Center( child: SizedBox( width: xAxisData.length * - (40 + 10), // Bar width + manual spacing + (80 + 10), // Bar width + manual spacing child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, @@ -1844,15 +2270,15 @@ class ChartWidget extends StatelessWidget { return Padding( padding: const EdgeInsets.only( - top: 8.0, - left: 75.0, + top: 0, + left: 0, ), child: SizedBox( width: 100, // Limit width to force wrapping child: Transform.rotate( // angle: -0.5, - angle: -1.5, + angle: 0, child: TooltipTheme( data: TooltipThemeData( @@ -1878,7 +2304,7 @@ class ChartWidget extends StatelessWidget { // title, displayTitle, softWrap: true, - textAlign: TextAlign.right, + textAlign: TextAlign.center, style: TextStyle(fontFamily: context.translate( 'Roboto', 'NotoKufi', @@ -1896,7 +2322,7 @@ class ChartWidget extends StatelessWidget { } return Container(); }, - reservedSize: 110, + reservedSize: 50, ), ), topTitles: AxisTitles( @@ -1931,7 +2357,7 @@ class ChartWidget extends StatelessWidget { toY: value == 0 ? 0.1 : value, color: bodyColor, borderRadius: BorderRadius.circular(4), - width: 20, + width: 35, ), ], showingTooltipIndicators: [0], @@ -2219,6 +2645,7 @@ class ChartWidget extends StatelessWidget { ) { return MapEntry(key, _hexToColor(value)); }); + print('parsedChartBarColors1100 $parsedChartBarColors'); if (kDebugMode) { print('Converted barColorsMap: $barColorsMap'); @@ -4368,6 +4795,7 @@ class ChartWidget extends StatelessWidget { colorIndex % 2]; // Alternate between two colors colorIndex++; // Update index for next bar } else { + print('check fl chart'); // barColor = chartBarColors[gender] ?? Colors.grey; // Default gender-based color barColor = chartBarColors[normalizedGender] ?? Colors.grey; } diff --git a/lib/presentation/components/constant/constant.dart b/lib/presentation/components/constant/constant.dart index b5422547..6fbc00ab 100644 --- a/lib/presentation/components/constant/constant.dart +++ b/lib/presentation/components/constant/constant.dart @@ -16,4 +16,4 @@ TextStyle subtitleStyle(BuildContext context) { TextStyle robotoRegular11(BuildContext context) {return TextStyle(fontFamily: context.translate('Roboto', 'NotoKufi'), fontWeight: FontWeight.w400, - fontSize: 11 * 1.1,color: Color(0xFF000000),);} + fontSize: 12 * 1.1,color: Color(0xFF000000),);} diff --git a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart index 245038d0..f9332ee8 100644 --- a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart +++ b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart @@ -1571,7 +1571,7 @@ class InfoCard extends StatelessWidget { Text( title, style: TextStyle( - fontSize: 11, + fontSize: 13, fontWeight: FontWeight.w400, letterSpacing: 0, // color: Colors.black, From fddc10f81f2275a99e9f8dffe38c4646d75a70f1 Mon Sep 17 00:00:00 2001 From: Kalonkarthik Date: Thu, 12 Jun 2025 11:53:56 +0530 Subject: [PATCH 2/2] firebase hosting --- .../arm64-v8a/configure_fingerprint.bin | 24 +++++++++---------- .../armeabi-v7a/configure_fingerprint.bin | 24 +++++++++---------- .../29y7472m/x86/configure_fingerprint.bin | 24 +++++++++---------- .../29y7472m/x86_64/configure_fingerprint.bin | 24 +++++++++---------- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/android/app/.cxx/Debug/29y7472m/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/29y7472m/arm64-v8a/configure_fingerprint.bin index 8dd99965..a814f3a4 100644 --- a/android/app/.cxx/Debug/29y7472m/arm64-v8a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/29y7472m/arm64-v8a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logo m kC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2l +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2l j -hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\android_gradle_build.json  2 2q +hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\android_gradle_build.json  2 2q o -mC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\android_gradle_build_mini.json  2 2^ +mC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\android_gradle_build_mini.json  2 2^ \ -ZC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\build.ninja  2 2b +ZC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\build.ninja  2 2b ` -^C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\build.ninja.txt  2g +^C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\build.ninja.txt  2g e -cC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\build_file_index.txt  2 K 2h +cC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\build_file_index.txt  2 K 2h f -dC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\compile_commands.json  2l +dC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\compile_commands.json  2l j -hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\compile_commands.json.bin  2 r +hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\compile_commands.json.bin  2 r p -nC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\metadata_generation_command.txt  2 +nC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\metadata_generation_command.txt  2  2e c -aC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\prefab_config.json  2  ( 2j +aC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\prefab_config.json  2  ( 2j h -fC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\symbol_folder_index.txt  2  ] 2O +fC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\arm64-v8a\symbol_folder_index.txt  2  ] 2O M -KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/29y7472m/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/29y7472m/armeabi-v7a/configure_fingerprint.bin index 381bb45f..039eea23 100644 --- a/android/app/.cxx/Debug/29y7472m/armeabi-v7a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/29y7472m/armeabi-v7a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logq o mC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2n +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ӓ2  2n l -jC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\android_gradle_build.json  2 2s +jC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\android_gradle_build.json  ԓ2 2s q -oC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\android_gradle_build_mini.json  2 2` +oC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\android_gradle_build_mini.json  ԓ2 2` ^ -\C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\build.ninja  2 2d +\C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\build.ninja  ԓ2 2d b -`C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\build.ninja.txt  2i +`C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\build.ninja.txt  ԓ2i g -eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\build_file_index.txt  2 K 2j +eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\build_file_index.txt  ԓ2 K 2j h -fC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\compile_commands.json  2n +fC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\compile_commands.json  ԓ2n l -jC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\compile_commands.json.bin  2 t +jC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\compile_commands.json.bin  ԓ2 t r -pC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\metadata_generation_command.txt  2 +pC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\metadata_generation_command.txt  ԓ2  É2g e -cC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\prefab_config.json  2  ( 2l +cC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\prefab_config.json  ԓ2  ( 2l j -hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\symbol_folder_index.txt  2  _ 닃2O +hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\armeabi-v7a\symbol_folder_index.txt  ԓ2  _ 닃2O M -KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  ԓ2  2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/29y7472m/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/29y7472m/x86/configure_fingerprint.bin index 573f7671..4e19963b 100644 --- a/android/app/.cxx/Debug/29y7472m/x86/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/29y7472m/x86/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logi g eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2f +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2f d -bC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\android_gradle_build.json  2 2k +bC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\android_gradle_build.json  2 2k i -gC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\android_gradle_build_mini.json  2 2X +gC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\android_gradle_build_mini.json  2 2X V -TC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\build.ninja  2 2\ +TC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\build.ninja  2 2\ Z -XC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\build.ninja.txt  2a +XC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\build.ninja.txt  2a _ -]C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\build_file_index.txt  2 K 2b +]C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\build_file_index.txt  2 K 2b ` -^C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\compile_commands.json  2f +^C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\compile_commands.json  2f d -bC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\compile_commands.json.bin  2 l +bC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\compile_commands.json.bin  2 l j -hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\metadata_generation_command.txt  2 +hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\metadata_generation_command.txt  2  2_ ] -[C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\prefab_config.json  2  ( 2d +[C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\prefab_config.json  2  ( 2d b -`C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\symbol_folder_index.txt  2  W 2O +`C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86\symbol_folder_index.txt  2  W 2O M -KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file +KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/29y7472m/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/29y7472m/x86_64/configure_fingerprint.bin index bcd28cb6..13d1ae16 100644 --- a/android/app/.cxx/Debug/29y7472m/x86_64/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/29y7472m/x86_64/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logl j hC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ź2  2i +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  2  2i g -eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\android_gradle_build.json  ź2 2n +eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\android_gradle_build.json  2 2n l -jC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\android_gradle_build_mini.json  ź2 2[ +jC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\android_gradle_build_mini.json  2 2[ Y -WC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\build.ninja  ź2 2_ +WC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\build.ninja  2 2_ ] -[C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\build.ninja.txt  ź2d +[C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\build.ninja.txt  2d b -`C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\build_file_index.txt  ź2 K 2e +`C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\build_file_index.txt  2 K 2e c -aC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\compile_commands.json  ź2i +aC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\compile_commands.json  2i g -eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\compile_commands.json.bin  ź2 o +eC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\compile_commands.json.bin  2 o m -kC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\metadata_generation_command.txt  ź2 +kC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\metadata_generation_command.txt  2  2b ` -^C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\prefab_config.json  ź2  ( 2g +^C:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\prefab_config.json  2  ( 2g e -cC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\symbol_folder_index.txt  ź2  Z 2O +cC:\Flutter Applications\Git_New\FCSC\android\app\.cxx\Debug\29y7472m\x86_64\symbol_folder_index.txt  2  Z 2O M -KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  ź2  2 \ No newline at end of file +KC:\src\flutter\packages\flutter_tools\gradle\src\main\groovy\CMakeLists.txt  2  2 \ No newline at end of file