bhavin feedback changes

This commit is contained in:
Surendiran 2025-06-12 11:45:26 +05:30
parent ebf5b5e853
commit f6c14eb2e5
4 changed files with 615 additions and 183 deletions

View File

@ -1462,6 +1462,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
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<ChartScreen1> {
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<ChartScreen1> {
Navigator.pop(context);
} else {
setState(() {
isLoading = true;
// isLoading = true;
chartsData = originalTabChartsData;
cardData = originalTabCardData;
});

View File

@ -90,20 +90,28 @@ class ChartWidget extends StatelessWidget {
// Function to get colors for both English & Arabic keys
List<Color> get uniqueColors {
final Map<String, String> 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<Color> get uniqueColorsForTwo {
final Map<String, String> translations = {
'الاقتصاد': 'ECONOMY',
'الاجتماعي': 'SOCIAL',
'البيئة': 'ENVIRONMENT',
'اقتصاد': 'ECONOMY',
'اجتماعي': 'SOCIAL',
'بيئة': 'ENVIRONMENT',
};
String key = translations[chartHeader] ?? chartHeader;
@ -112,9 +120,9 @@ class ChartWidget extends StatelessWidget {
List<Color> get uniqueColorsForThree {
final Map<String, String> translations = {
'الاقتصاد': 'ECONOMY',
'الاجتماعي': 'SOCIAL',
'البيئة': 'ENVIRONMENT',
'اقتصاد': 'ECONOMY',
'اجتماعي': 'SOCIAL',
'بيئة': 'ENVIRONMENT',
};
String key = translations[chartHeader] ?? chartHeader;
@ -1271,12 +1279,7 @@ class ChartWidget extends StatelessWidget {
Set<int> selectedYears = {1970, 1980, 1990, 2000, 2010, 2020};
Map<String, Color> 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<int> years = (chartData['response'] as List<dynamic>)
@ -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<dynamic, dynamic> to Map<String, String>
// Map<String, String> chartBarColrs =
// Map<String, String>.from(chartBarColorsRaw);
// // Now map to Color
// Map<String, Color> parsedChartBarColors =
// chartBarColrs.map((key, value) {
// return MapEntry(key, _hexToColor(value));
// });
//
List<dynamic> keys = chartBarColors['key'] ?? [];
List<dynamic> colors = chartBarColors['color'] ?? [];
@ -1359,109 +1353,288 @@ class ChartWidget extends StatelessWidget {
colorIndex++;
}
// Generate line bars for the chart
List<LineChartBarData> 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<String, List<Map<String, dynamic>>> 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<LineChartBarData>
final List<LineChartBarData> lineBars = [];
final List<Color> 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<FlSpot> 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<Color> uniqueColorsLine_trend_2 = [
// Color(0xFF6097CD),
// Color(0xFFD086A7),
// Color(0xFF98BCE5),
// Color(0xFFA7B5C5),
// Color(0xFFBED3EC),
// Color(0xFFD4E3F4),
// ];
final List<Color> uniqueColorsLine_trend_2 = [
Color(0xFF6097CD),
Color(0xFFD086A7),
];
Set<int> selectedYears = {1970, 1980, 1990, 2000, 2010, 2020};
Map<String, Color> 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<int> years = (chartData['response'] as List<dynamic>)
.map<int>(
(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<dynamic> filteredData =
(chartData['response'] as List<dynamic>).where((entry) {
(chartData['response'] as List<dynamic>).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<double> uniqueXValues = filteredData
.map<double>(
(entry) => double.parse(entry['ObsKey']['TIME_PERIOD']),
)
)
.toSet();
print('uniqueXValuesLineTrend2- $uniqueXValues');
var chartBarColors = chartData['chart_bar_color'] ?? {};
Map<String, String> 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<dynamic, dynamic> to Map<String, String>
Map<String, String> chartBarColrs = Map<String, String>.from(
chartBarColorsRaw,
);
List<dynamic> keys = chartBarColors['key'] ?? [];
List<dynamic> colors = chartBarColors['color'] ?? [];
// Now map to Color
Map<String, Color> parsedChartBarColors = chartBarColrs.map((
key,
value,
) {
return MapEntry(key, _hexToColor(value));
});
print('RT1keys - $keys');
print('RT1colors - $colors');
// Convert to a map for easy lookup
Map<String, Color> 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<LineChartBarData> 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<String, List<Map<String, dynamic>>> 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<LineChartBarData>
final List<LineChartBarData> lineBars = [];
final List<Color> 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<int, Map<String, double>> 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<FlSpot> 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<FlSpot> 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;
}

View File

@ -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),);}

View File

@ -1571,7 +1571,7 @@ class InfoCard extends StatelessWidget {
Text(
title,
style: TextStyle(
fontSize: 11,
fontSize: 13,
fontWeight: FontWeight.w400,
letterSpacing: 0,
// color: Colors.black,