charts bug fix
This commit is contained in:
parent
feca758194
commit
80fc023b4a
@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
|
|||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||||
if (flutterVersionCode == null) {
|
if (flutterVersionCode == null) {
|
||||||
flutterVersionCode = "20"
|
flutterVersionCode = "21"
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||||
if (flutterVersionName == null) {
|
if (flutterVersionName == null) {
|
||||||
flutterVersionName = "1.0.19"
|
flutterVersionName = "1.0.20"
|
||||||
}
|
}
|
||||||
|
|
||||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||||
|
|||||||
@ -2330,6 +2330,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
right: 16.0,
|
right: 16.0,
|
||||||
bottom: 1.0,
|
bottom: 1.0,
|
||||||
top: 1.0),
|
top: 1.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white, // Move color inside BoxDecoration
|
||||||
|
borderRadius: BorderRadius.circular(12), // Ensure border radius is applied
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
@ -2373,6 +2377,8 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Flexible(
|
Flexible(
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 20.0,
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
'(${response[0]['display_value'] ?? 'NA'})',
|
'(${response[0]['display_value'] ?? 'NA'})',
|
||||||
@ -2384,6 +2390,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
color: Colors.grey),
|
color: Colors.grey),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 1),
|
const SizedBox(height: 1),
|
||||||
Flexible(
|
Flexible(
|
||||||
@ -2441,6 +2448,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
height: cardHeight,
|
height: cardHeight,
|
||||||
padding: const EdgeInsets.all(10.0),
|
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(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize
|
mainAxisSize: MainAxisSize
|
||||||
.min, // Adjust card height based on content
|
.min, // Adjust card height based on content
|
||||||
@ -2574,24 +2585,42 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.all(10),
|
margin: const EdgeInsets.all(10),
|
||||||
|
child: Container(
|
||||||
|
|
||||||
|
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Color(int.parse((chartScreenData[
|
||||||
|
'border_color'] ?? '#898C81')
|
||||||
|
.replaceFirst('#', '0xff'),),), // Border color
|
||||||
|
width: 1, // Border width
|
||||||
|
),
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8), // Optional: Rounded corners
|
||||||
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 10),
|
|
||||||
ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(
|
// ConstrainedBox
|
||||||
minHeight:
|
Container
|
||||||
200, // Minimum height
|
(
|
||||||
maxHeight:
|
// constraints: const BoxConstraints(
|
||||||
400, // Maximum height
|
// minHeight:
|
||||||
),
|
// 200, // Minimum height
|
||||||
// child: buildChart(chartsData[index]),
|
// maxHeight:
|
||||||
child: ChartWidget(
|
// 400, // Maximum height
|
||||||
chartData:
|
// ),
|
||||||
chartsData[index])),
|
height: 320,
|
||||||
|
|
||||||
|
// child: buildChart(chartsData[index]),
|
||||||
|
child: ChartWidget(
|
||||||
|
chartData:
|
||||||
|
chartsData[index]))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -55,9 +55,30 @@ class ChartWidget extends StatelessWidget {
|
|||||||
.entries
|
.entries
|
||||||
.map<PieChartSectionData>((entry) {
|
.map<PieChartSectionData>((entry) {
|
||||||
int index = entry.key;
|
int index = entry.key;
|
||||||
|
|
||||||
|
print('piePArse');
|
||||||
|
|
||||||
var data = entry.value;
|
var data = entry.value;
|
||||||
double value = double.tryParse(data['ObsValue']['Value']) ?? 0.0;
|
// double value = double.tryParse(data['ObsValue']['Value']) ?? 0.0;
|
||||||
double percentage = (value / totalValue) * 100;
|
// double value = (data['ObsValue']['Value'] is double)
|
||||||
|
// ? data['ObsValue']['Value']
|
||||||
|
// : (data['ObsValue']['Value'] is int)
|
||||||
|
// ? (data['ObsValue']['Value'] as int).toDouble()
|
||||||
|
// : 0.0;
|
||||||
|
|
||||||
|
// Handle different types: int, double, and String
|
||||||
|
double value = 0.0;
|
||||||
|
|
||||||
|
if (data['ObsValue']['Value'] is String) {
|
||||||
|
value = double.tryParse(data['ObsValue']['Value']) ?? 0.0; // Parse string to double
|
||||||
|
} else if (data['ObsValue']['Value'] is int) {
|
||||||
|
value = (data['ObsValue']['Value'] as int).toDouble(); // Convert int to double
|
||||||
|
} else if (data['ObsValue']['Value'] is double) {
|
||||||
|
value = data['ObsValue']['Value']; // Already a double
|
||||||
|
}
|
||||||
|
|
||||||
|
print('piePArse1 - $value');
|
||||||
|
double percentage = (value / totalValue) * 100;
|
||||||
bool isTouched = index == touchedIndex;
|
bool isTouched = index == touchedIndex;
|
||||||
return PieChartSectionData(
|
return PieChartSectionData(
|
||||||
value: value,
|
value: value,
|
||||||
@ -94,14 +115,22 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Tooltip(
|
TooltipTheme(
|
||||||
|
data: TooltipThemeData(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blueGrey[800], // Change background color
|
||||||
|
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
||||||
|
),
|
||||||
|
textStyle: TextStyle(color: Colors.white), // Change text color
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
message: title, // Full text on hover
|
message: title, // Full text on hover
|
||||||
child: Text(
|
child: Text(
|
||||||
shortTitle,
|
shortTitle,
|
||||||
style: TextStyle(fontSize: 12),
|
style: TextStyle(fontSize: 12),
|
||||||
overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
|
overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
|
||||||
),
|
),
|
||||||
),
|
),),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -214,8 +243,11 @@ class ChartWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
case 'pie_chart':
|
case 'pie_chart':
|
||||||
double totalValue = chartData['response']
|
double totalValue = chartData['response']
|
||||||
.map<double>(
|
.map<double>((entry) {
|
||||||
(entry) => double.tryParse(entry['ObsValue']['Value']) ?? 0.0)
|
var value = entry['ObsValue']['Value'];
|
||||||
|
print('Processing value: $value, type: ${value.runtimeType}'); // Debug each value
|
||||||
|
return value is int ? value.toDouble() : value is String ? double.tryParse(value) ?? 0.0 : 0.0;
|
||||||
|
})
|
||||||
.fold(0.0, (prev, element) => prev + element);
|
.fold(0.0, (prev, element) => prev + element);
|
||||||
|
|
||||||
ValueNotifier<int?> touchedIndex = ValueNotifier(null);
|
ValueNotifier<int?> touchedIndex = ValueNotifier(null);
|
||||||
@ -240,7 +272,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 40),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ValueListenableBuilder<int?>(
|
child: ValueListenableBuilder<int?>(
|
||||||
valueListenable: touchedIndex,
|
valueListenable: touchedIndex,
|
||||||
@ -266,22 +299,24 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 25),
|
SizedBox(height:60),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints:
|
// constraints:
|
||||||
BoxConstraints(minHeight: 5), // Allow dynamic height
|
// BoxConstraints(minHeight: 5), // Allow dynamic height
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 8.0, right: 8.0, bottom: 8.0, top: 20.0),
|
left: 0.0, right: 0.0, bottom: 8.0, top: 20.0),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 12,
|
// spacing: 12,
|
||||||
runSpacing: 8,
|
// runSpacing: 8,
|
||||||
children:
|
children:
|
||||||
generateIndicators(chartData, chartData['group_by']),
|
generateIndicators(chartData, chartData['group_by']),
|
||||||
),
|
),
|
||||||
@ -325,7 +360,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 15),
|
||||||
AspectRatio(
|
AspectRatio(
|
||||||
aspectRatio: 1.5,
|
aspectRatio: 1.5,
|
||||||
child: BarChart(
|
child: BarChart(
|
||||||
@ -336,8 +371,12 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// tooltipBgColor: Colors.black.withOpacity(0.8),
|
// tooltipBgColor: Colors.black.withOpacity(0.8),
|
||||||
fitInsideHorizontally: true,
|
fitInsideHorizontally: true,
|
||||||
fitInsideVertically: true,
|
fitInsideVertically: true,
|
||||||
tooltipPadding: const EdgeInsets.all(8),
|
// tooltipPadding: const EdgeInsets.all(8),
|
||||||
|
tooltipPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8), // Optional
|
||||||
|
tooltipHorizontalAlignment: FLHorizontalAlignment.left,
|
||||||
tooltipMargin: 16,
|
tooltipMargin: 16,
|
||||||
|
|
||||||
|
|
||||||
getTooltipItem:
|
getTooltipItem:
|
||||||
(groupData, groupIndex, rodData, rodIndex) {
|
(groupData, groupIndex, rodData, rodIndex) {
|
||||||
// Get the list of group names dynamically
|
// Get the list of group names dynamically
|
||||||
@ -395,6 +434,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
'',
|
'',
|
||||||
TextStyle(color: Colors.white, fontSize: 12),
|
TextStyle(color: Colors.white, fontSize: 12),
|
||||||
children: tooltipTextSpans,
|
children: tooltipTextSpans,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -458,7 +498,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
waitDuration: Duration(milliseconds: 500),
|
waitDuration: Duration(milliseconds: 500),
|
||||||
showDuration: Duration(seconds: 2),
|
showDuration: Duration(seconds: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black,
|
color: Colors.blueGrey[900],
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
textStyle: TextStyle(color: Colors.white),
|
textStyle: TextStyle(color: Colors.white),
|
||||||
@ -535,7 +575,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
Set<String> uniqueXValues = filteredData
|
Set<String> uniqueXValues = filteredData
|
||||||
.map<String>((entry) {
|
.map<String>((entry) {
|
||||||
String? timePeriod = entry['ObsKey']['TIME_PERIOD']; // Nullable String
|
String? timePeriod = entry['ObsKey']['TIME_PERIOD']; // Nullable String
|
||||||
// print('TIME_PERIOD- $timePeriod');
|
print('TIME_PERIOD- $timePeriod');
|
||||||
|
|
||||||
if (timePeriod == null) {
|
if (timePeriod == null) {
|
||||||
print('TIME_PERIOD is null');
|
print('TIME_PERIOD is null');
|
||||||
@ -859,7 +899,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
|
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
|
||||||
padding: const EdgeInsets.only(right: 40),
|
padding: const EdgeInsets.only(right: 40, top: 20),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: (uniqueXValues.length * 50) +
|
width: (uniqueXValues.length * 50) +
|
||||||
50, // Adjust width dynamically
|
50, // Adjust width dynamically
|
||||||
@ -919,7 +959,23 @@ class ChartWidget extends StatelessWidget {
|
|||||||
maxY: yAxisData.isNotEmpty
|
maxY: yAxisData.isNotEmpty
|
||||||
? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2
|
? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2
|
||||||
: 10,
|
: 10,
|
||||||
barTouchData: BarTouchData(enabled: true),
|
// barTouchData: BarTouchData(enabled: true),
|
||||||
|
barTouchData: BarTouchData(
|
||||||
|
enabled: true,
|
||||||
|
handleBuiltInTouches: true,
|
||||||
|
touchTooltipData: BarTouchTooltipData(
|
||||||
|
// fitInsideHorizontally: true,
|
||||||
|
// fitInsideVertically: true,
|
||||||
|
// tooltipPadding: const EdgeInsets.all(8),
|
||||||
|
// tooltipMargin: 16,
|
||||||
|
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||||
|
return BarTooltipItem(
|
||||||
|
rod.toY.toStringAsFixed(1),
|
||||||
|
const TextStyle(color: Colors.white),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
titlesData: FlTitlesData(
|
titlesData: FlTitlesData(
|
||||||
leftTitles: AxisTitles(
|
leftTitles: AxisTitles(
|
||||||
sideTitles: SideTitles(
|
sideTitles: SideTitles(
|
||||||
@ -948,23 +1004,49 @@ class ChartWidget extends StatelessWidget {
|
|||||||
: title;
|
: title;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding: const EdgeInsets.only(top: 8.0,left: 25.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 60, // Limit width to force wrapping
|
width: 60, // Limit width to force wrapping
|
||||||
child: Transform.rotate(
|
child: Transform.rotate(
|
||||||
angle: -0.5,
|
// angle: -0.5,
|
||||||
child: Tooltip(
|
angle: -1.5,
|
||||||
|
|
||||||
|
child: TooltipTheme(
|
||||||
|
data: TooltipThemeData(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blueGrey[800], // Change background color
|
||||||
|
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
||||||
|
),
|
||||||
|
textStyle: TextStyle(color: Colors.white), // Change text color
|
||||||
|
),
|
||||||
|
|
||||||
|
child: TooltipTheme(
|
||||||
|
data: TooltipThemeData(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blueGrey[800], // Change background color
|
||||||
|
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
||||||
|
),
|
||||||
|
textStyle: TextStyle(color: Colors.white), // Change text color
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
message: title,
|
message: title,
|
||||||
|
|
||||||
child: Text(
|
child: Text(
|
||||||
|
// title,
|
||||||
displayTitle,
|
displayTitle,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
|
style: TextStyle(fontSize: 10,),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
)),
|
),),
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
return Container();
|
return Container();
|
||||||
},
|
},
|
||||||
reservedSize: 40,
|
reservedSize: 80,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
topTitles: AxisTitles(
|
topTitles: AxisTitles(
|
||||||
@ -1087,7 +1169,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
xAxisData[value.toInt()],
|
xAxisData[value.toInt()],
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
maxLines: 2,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1144,7 +1226,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
|
|
||||||
for (var item in chartData['response']) {
|
for (var item in chartData['response']) {
|
||||||
|
|
||||||
// print("MultiBArRaw item: $item");
|
print("MultiBArRaw item: $item");
|
||||||
|
|
||||||
String crop = item['ObsKey'][cropKey];
|
String crop = item['ObsKey'][cropKey];
|
||||||
String cropType = item['ObsKey'][groupByKey];
|
String cropType = item['ObsKey'][groupByKey];
|
||||||
@ -1174,184 +1256,197 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// print('groupedCropsflmutli- $groupedCrops');
|
// print('groupedCropsflmutli- $groupedCrops');
|
||||||
|
|
||||||
|
|
||||||
return Column(children: [
|
return Center(
|
||||||
Text(
|
child: Column(children: [
|
||||||
chartData['chart_heading'] ?? '', // Chart title from data
|
Text(
|
||||||
style: TextStyle(
|
chartData['chart_heading'] ?? '', // Chart title from data
|
||||||
fontSize: 14,
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w400,
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
SizedBox(height: 5),
|
||||||
),
|
Text(
|
||||||
SizedBox(height: 5),
|
chartData['chart_sub_heading'] ?? '',
|
||||||
Text(
|
style: TextStyle(
|
||||||
chartData['chart_sub_heading'] ?? '',
|
fontSize: 13,
|
||||||
style: TextStyle(
|
fontWeight: FontWeight.w300,
|
||||||
fontSize: 13,
|
),
|
||||||
fontWeight: FontWeight.w300,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
SizedBox(height: 10),
|
||||||
),
|
// Chart
|
||||||
SizedBox(height: 10),
|
Expanded(
|
||||||
// Chart
|
child: SingleChildScrollView(
|
||||||
Expanded(
|
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
|
||||||
child: SingleChildScrollView(
|
child: SizedBox(
|
||||||
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
|
width: _calculateChartWidth(
|
||||||
child: SizedBox(
|
chartData), // Dynamically calculate the chart width
|
||||||
width: _calculateChartWidth(
|
child: BarChart(
|
||||||
chartData), // Dynamically calculate the chart width
|
BarChartData(
|
||||||
child: BarChart(
|
alignment: BarChartAlignment.spaceAround,
|
||||||
BarChartData(
|
maxY:
|
||||||
alignment: BarChartAlignment.spaceAround,
|
_calculateMaxY(chartData), // Dynamically calculate max Y
|
||||||
maxY:
|
barGroups: _buildHorizontalRotateBarGroups(
|
||||||
_calculateMaxY(chartData), // Dynamically calculate max Y
|
chartData, groupByValues), // Build bar groups
|
||||||
barGroups: _buildHorizontalRotateBarGroups(
|
titlesData: FlTitlesData(
|
||||||
chartData, groupByValues), // Build bar groups
|
leftTitles: AxisTitles(
|
||||||
titlesData: FlTitlesData(
|
sideTitles: SideTitles(showTitles: false),
|
||||||
leftTitles: AxisTitles(
|
),
|
||||||
sideTitles: SideTitles(showTitles: false),
|
bottomTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 40, // Added space for rotated titles
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
if (value < groupByValues.length) {
|
||||||
|
String title =
|
||||||
|
groupByValues.elementAt(value.toInt());
|
||||||
|
|
||||||
|
String displayTitle = title.length > 10
|
||||||
|
? title.substring(0, 10) + '...'
|
||||||
|
: title;
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 60, // Limit width to force wrapping
|
||||||
|
child: Transform.rotate(
|
||||||
|
angle: -0.5,
|
||||||
|
child: TooltipTheme(
|
||||||
|
data: TooltipThemeData(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blueGrey[800], // Change background color
|
||||||
|
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
||||||
|
),
|
||||||
|
textStyle: TextStyle(color: Colors.white), // Change text color
|
||||||
|
),
|
||||||
|
child: Tooltip(
|
||||||
|
message: title,
|
||||||
|
child: Text(
|
||||||
|
displayTitle,
|
||||||
|
softWrap: true,
|
||||||
|
// style: TextStyle(backgroundColor: Colors.blueGrey[800]),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
)),
|
||||||
|
|
||||||
|
),
|
||||||
|
)));
|
||||||
|
// return Transform.rotate(
|
||||||
|
// angle:
|
||||||
|
// -0.5, // Rotation in radians (~ -30 degrees)
|
||||||
|
// child: Text(
|
||||||
|
// title,
|
||||||
|
// style: const TextStyle(fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
topTitles:
|
||||||
|
AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||||
|
rightTitles:
|
||||||
|
AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||||
),
|
),
|
||||||
bottomTitles: AxisTitles(
|
borderData: FlBorderData(show: false),
|
||||||
sideTitles: SideTitles(
|
barTouchData: BarTouchData(
|
||||||
showTitles: true,
|
touchTooltipData: BarTouchTooltipData(
|
||||||
reservedSize: 40, // Added space for rotated titles
|
tooltipHorizontalAlignment: FLHorizontalAlignment.center,
|
||||||
getTitlesWidget: (value, meta) {
|
tooltipRoundedRadius: 8,
|
||||||
if (value < groupByValues.length) {
|
fitInsideHorizontally:
|
||||||
String title =
|
true, // Ensure it fits within the screen
|
||||||
groupByValues.elementAt(value.toInt());
|
fitInsideVertically: true,
|
||||||
|
tooltipPadding: EdgeInsets.all(8),
|
||||||
String displayTitle = title.length > 10
|
tooltipMargin: 16,
|
||||||
? title.substring(0, 10) + '...'
|
// Only show tooltip when touched
|
||||||
: title;
|
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||||
|
if (rod.toY == 0 || touchedGroupIndex == -1) {
|
||||||
return Padding(
|
return null; // Don't show the tooltip if the value is 0 or there's no touch
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: SizedBox(
|
|
||||||
width: 60, // Limit width to force wrapping
|
|
||||||
child: Transform.rotate(
|
|
||||||
angle: -0.5,
|
|
||||||
child: Tooltip(
|
|
||||||
message: title,
|
|
||||||
child: Text(
|
|
||||||
displayTitle,
|
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
)),
|
|
||||||
)));
|
|
||||||
// return Transform.rotate(
|
|
||||||
// angle:
|
|
||||||
// -0.5, // Rotation in radians (~ -30 degrees)
|
|
||||||
// child: Text(
|
|
||||||
// title,
|
|
||||||
// style: const TextStyle(fontSize: 12),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
return const SizedBox.shrink();
|
if (groupIndex == touchedGroupIndex) {
|
||||||
|
// Get the group label dynamically
|
||||||
|
String groupLabel =
|
||||||
|
groupByValues.elementAt(groupIndex);
|
||||||
|
|
||||||
|
// Fetch the crop for the current group from groupedCrops
|
||||||
|
String cropType = groupByValues.elementAt(groupIndex);
|
||||||
|
print('GrpcropType: $cropType');
|
||||||
|
// String crop = groupedCrops[cropType]![rodIndex];
|
||||||
|
|
||||||
|
// Safely fetch crop with null check
|
||||||
|
List<String>? crops = groupedCrops[cropType];
|
||||||
|
String crop;
|
||||||
|
if (crops != null && rodIndex < crops.length) {
|
||||||
|
crop = crops[rodIndex];
|
||||||
|
} else {
|
||||||
|
print(
|
||||||
|
'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex');
|
||||||
|
// crop = cropType; // Fallback to cropType
|
||||||
|
crop = (crops != null && crops.isNotEmpty) ? crops.first : cropType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print('groupedCrops1: $groupedCrops - $rodIndex');
|
||||||
|
// print(
|
||||||
|
// 'Groupcrop: $crop');
|
||||||
|
double value = rod.toY;
|
||||||
|
|
||||||
|
String formattedValue;
|
||||||
|
if (value >= 1000000) {
|
||||||
|
formattedValue =
|
||||||
|
(value / 1000000).toStringAsFixed(1) + 'M';
|
||||||
|
} else if (value >= 1000) {
|
||||||
|
formattedValue =
|
||||||
|
(value / 1000).toStringAsFixed(1) + 'K';
|
||||||
|
} else {
|
||||||
|
formattedValue = value.toStringAsFixed(
|
||||||
|
0); // for values smaller than 1000
|
||||||
|
}
|
||||||
|
// print('Cropvaluevalue: $groupLabel\n$crop $value $formattedValue');
|
||||||
|
|
||||||
|
return BarTooltipItem(
|
||||||
|
'$groupLabel\n$crop',
|
||||||
|
const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
// text: ' Value: ${rod.toY}',
|
||||||
|
text: ' Value: $formattedValue',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.yellow,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
touchCallback: (event, response) {
|
||||||
topTitles:
|
if (event.isInterestedForInteractions &&
|
||||||
AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
response != null &&
|
||||||
rightTitles:
|
response.spot != null) {
|
||||||
AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
// setState(() {
|
||||||
),
|
touchedGroupIndex = response.spot!.touchedBarGroupIndex;
|
||||||
borderData: FlBorderData(show: false),
|
// });
|
||||||
barTouchData: BarTouchData(
|
} else {
|
||||||
touchTooltipData: BarTouchTooltipData(
|
// setState(() {
|
||||||
tooltipHorizontalAlignment: FLHorizontalAlignment.center,
|
touchedGroupIndex = -1; // Reset if no interaction
|
||||||
tooltipRoundedRadius: 8,
|
// });
|
||||||
fitInsideHorizontally:
|
|
||||||
true, // Ensure it fits within the screen
|
|
||||||
fitInsideVertically: true,
|
|
||||||
tooltipPadding: EdgeInsets.all(8),
|
|
||||||
tooltipMargin: 16,
|
|
||||||
// Only show tooltip when touched
|
|
||||||
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
|
||||||
if (rod.toY == 0 || touchedGroupIndex == -1) {
|
|
||||||
return null; // Don't show the tooltip if the value is 0 or there's no touch
|
|
||||||
}
|
}
|
||||||
if (groupIndex == touchedGroupIndex) {
|
|
||||||
// Get the group label dynamically
|
|
||||||
String groupLabel =
|
|
||||||
groupByValues.elementAt(groupIndex);
|
|
||||||
|
|
||||||
// Fetch the crop for the current group from groupedCrops
|
|
||||||
String cropType = groupByValues.elementAt(groupIndex);
|
|
||||||
print('GrpcropType: $cropType');
|
|
||||||
// String crop = groupedCrops[cropType]![rodIndex];
|
|
||||||
|
|
||||||
// Safely fetch crop with null check
|
|
||||||
List<String>? crops = groupedCrops[cropType];
|
|
||||||
String crop;
|
|
||||||
if (crops != null && rodIndex < crops.length) {
|
|
||||||
crop = crops[rodIndex];
|
|
||||||
} else {
|
|
||||||
print(
|
|
||||||
'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex');
|
|
||||||
// crop = cropType; // Fallback to cropType
|
|
||||||
crop = (crops != null && crops.isNotEmpty) ? crops.first : cropType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print('groupedCrops1: $groupedCrops - $rodIndex');
|
|
||||||
// print(
|
|
||||||
// 'Groupcrop: $crop');
|
|
||||||
double value = rod.toY;
|
|
||||||
|
|
||||||
String formattedValue;
|
|
||||||
if (value >= 1000000) {
|
|
||||||
formattedValue =
|
|
||||||
(value / 1000000).toStringAsFixed(1) + 'M';
|
|
||||||
} else if (value >= 1000) {
|
|
||||||
formattedValue =
|
|
||||||
(value / 1000).toStringAsFixed(1) + 'K';
|
|
||||||
} else {
|
|
||||||
formattedValue = value.toStringAsFixed(
|
|
||||||
0); // for values smaller than 1000
|
|
||||||
}
|
|
||||||
// print('Cropvaluevalue: $groupLabel\n$crop $value $formattedValue');
|
|
||||||
|
|
||||||
return BarTooltipItem(
|
|
||||||
'$groupLabel\n$crop',
|
|
||||||
const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
// text: ' Value: ${rod.toY}',
|
|
||||||
text: ' Value: $formattedValue',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.yellow,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
touchCallback: (event, response) {
|
gridData: FlGridData(show: false),
|
||||||
if (event.isInterestedForInteractions &&
|
|
||||||
response != null &&
|
|
||||||
response.spot != null) {
|
|
||||||
// setState(() {
|
|
||||||
touchedGroupIndex = response.spot!.touchedBarGroupIndex;
|
|
||||||
// });
|
|
||||||
} else {
|
|
||||||
// setState(() {
|
|
||||||
touchedGroupIndex = -1; // Reset if no interaction
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
gridData: FlGridData(show: false),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
))
|
||||||
))
|
]),
|
||||||
]);
|
);
|
||||||
|
|
||||||
case 'horizontal_rotate':
|
case 'horizontal_rotate':
|
||||||
String cropKey = chartData['chart_type_json']
|
String cropKey = chartData['chart_type_json']
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
name: uae_stat
|
name: uae_stat
|
||||||
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.0.19+20
|
version: 1.0.20+21
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.2.3 <4.0.0"
|
sdk: ">=3.2.3 <4.0.0"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user