chart changes done
This commit is contained in:
parent
3cc3a9bcbd
commit
25eb1a06e9
@ -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 = "21"
|
flutterVersionCode = "24"
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||||
if (flutterVersionName == null) {
|
if (flutterVersionName == null) {
|
||||||
flutterVersionName = "1.0.20"
|
flutterVersionName = "1.0.23"
|
||||||
}
|
}
|
||||||
|
|
||||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
print(' bgColor $bgColor');
|
print(' bgColor $bgColor');
|
||||||
// fetchChartData(widget.dataSets);
|
// fetchChartData(widget.dataSets);
|
||||||
checkIfBookmarked();
|
checkIfBookmarked();
|
||||||
locale = ref.read(localeProvider)?? const Locale('en');
|
locale = ref.read(localeProvider) ?? const Locale('en');
|
||||||
fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) {
|
fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) {
|
||||||
if (_tabsData.isNotEmpty) {
|
if (_tabsData.isNotEmpty) {
|
||||||
// Call onTabSelected for the first tab
|
// Call onTabSelected for the first tab
|
||||||
@ -310,6 +310,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//when the popup need for bookmark
|
//when the popup need for bookmark
|
||||||
// void showAddBookmarkDialog() {
|
// void showAddBookmarkDialog() {
|
||||||
// double myheight = MediaQuery.of(context).size.height;
|
// double myheight = MediaQuery.of(context).size.height;
|
||||||
@ -398,15 +399,15 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
// }
|
// }
|
||||||
void showAddBookmarkDialog() {
|
void showAddBookmarkDialog() {
|
||||||
addBookmark();
|
addBookmark();
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
// ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
// SnackBar(
|
||||||
content: Text(
|
// content: Text(
|
||||||
'The bookmark is added successfully',
|
// 'The bookmark is added successfully',
|
||||||
),
|
// ),
|
||||||
backgroundColor: Colors.green,
|
// backgroundColor: Colors.green,
|
||||||
duration: Duration(seconds: 2),
|
// duration: Duration(seconds: 2),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSkip() {
|
void handleSkip() {
|
||||||
@ -539,9 +540,14 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null,
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: null,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: Colors.white,
|
||||||
|
width: 2.0),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
@ -551,8 +557,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
tutorialCoachMark.next();
|
tutorialCoachMark.next();
|
||||||
} else {
|
} else {
|
||||||
ref.read(chartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(previousHomeTourProvider.notifier).state = false;
|
.read(chartsTourProvider.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(previousHomeTourProvider
|
||||||
|
.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -562,9 +573,14 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC),
|
color: locale.languageCode == 'ar'
|
||||||
|
? null
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Colors.white: Color(0xFF7DAFBC), width: 1),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Colors.white
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
|
width: 1),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
@ -572,8 +588,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
color: Colors.white),
|
color: Colors.white),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
ref.read(chartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(previousHomeTourProvider.notifier).state = false;
|
.read(chartsTourProvider.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(previousHomeTourProvider
|
||||||
|
.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
} else {
|
} else {
|
||||||
tutorialCoachMark.next();
|
tutorialCoachMark.next();
|
||||||
@ -627,7 +648,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
text: AppLocalizations.of(context)!.bookMark,
|
text: AppLocalizations.of(context)!.bookMark,
|
||||||
alignment: ContentAlign.bottom,
|
alignment: ContentAlign.bottom,
|
||||||
gap: 53,
|
gap: 53,
|
||||||
space: screenWidth*0.22,
|
space: screenWidth * 0.22,
|
||||||
),
|
),
|
||||||
TargetContent(
|
TargetContent(
|
||||||
align: ContentAlign.bottom,
|
align: ContentAlign.bottom,
|
||||||
@ -682,18 +703,29 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null,
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: null,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: Colors.white,
|
||||||
|
width: 2.0),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
icon: const Icon(Icons.arrow_back,
|
icon: const Icon(
|
||||||
color: Colors.white,),
|
Icons.arrow_back,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
ref.read(chartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(scaffoldTourProvider.notifier).state = false;
|
.read(chartsTourProvider.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(scaffoldTourProvider.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
} else {
|
} else {
|
||||||
tutorialCoachMark.previous();
|
tutorialCoachMark.previous();
|
||||||
@ -705,23 +737,33 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC),
|
color: locale.languageCode == 'ar'
|
||||||
|
? null
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Colors.white: Color(0xFF7DAFBC), width: 1),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Colors.white
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
|
width: 1),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
icon: const Icon(Icons.arrow_forward,
|
icon: const Icon(
|
||||||
color: Colors.white,),
|
Icons.arrow_forward,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
tutorialCoachMark.previous();
|
tutorialCoachMark.previous();
|
||||||
} else {
|
} else {
|
||||||
ref.read(chartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(scaffoldTourProvider.notifier).state = false;
|
.read(chartsTourProvider.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(scaffoldTourProvider.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -741,7 +783,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
align: ContentAlign.right,
|
align: ContentAlign.right,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: screenWidth / 4,
|
width: screenWidth / 4,
|
||||||
height: screenHeight*0.2,
|
height: screenHeight * 0.2,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Image.asset(
|
||||||
@ -770,7 +812,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
contents: [
|
contents: [
|
||||||
createTargetContent(
|
createTargetContent(
|
||||||
text: AppLocalizations.of(context)!.bookMark,
|
text: AppLocalizations.of(context)!.bookMark,
|
||||||
space:screenWidth*0.22,
|
space: screenWidth * 0.22,
|
||||||
alignment: ContentAlign.bottom,
|
alignment: ContentAlign.bottom,
|
||||||
gap: 53,
|
gap: 53,
|
||||||
),
|
),
|
||||||
@ -827,18 +869,30 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null,
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: null,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0,),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: Colors.white,
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
icon: const Icon(Icons.arrow_back,
|
icon: const Icon(
|
||||||
color: Colors.white,),
|
Icons.arrow_back,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
ref.read(chartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(scaffoldTourProvider.notifier).state = false;
|
.read(chartsTourProvider.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(scaffoldTourProvider.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
} else {
|
} else {
|
||||||
tutorialCoachMark.next();
|
tutorialCoachMark.next();
|
||||||
@ -850,9 +904,15 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC),
|
color: locale.languageCode == 'ar'
|
||||||
|
? null
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Colors.white : Color(0xFF7DAFBC), width: 2.0,),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Colors.white
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
@ -862,8 +922,12 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
tutorialCoachMark.next();
|
tutorialCoachMark.next();
|
||||||
} else {
|
} else {
|
||||||
ref.read(chartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(scaffoldTourProvider.notifier).state = false;
|
.read(chartsTourProvider.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(scaffoldTourProvider.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -885,7 +949,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
align: ContentAlign.right,
|
align: ContentAlign.right,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: screenWidth / 4,
|
width: screenWidth / 4,
|
||||||
height:screenHeight*0.2,
|
height: screenHeight * 0.2,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Image.asset(
|
||||||
@ -964,23 +1028,36 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? Color(0xFF7DAFBC):null,
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: null,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Color(0xFF7DAFBC): Colors.white, width: 2.0,),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Color(0xFF7DAFBC)
|
||||||
|
: Colors.white,
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
icon: const Icon(Icons.arrow_back,
|
icon: const Icon(
|
||||||
color: Colors.white,),
|
Icons.arrow_back,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
tutorialCoachMark.previous();
|
tutorialCoachMark.previous();
|
||||||
} else {
|
} else {
|
||||||
ref.read(previousChartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(previousHomeTourProvider.notifier).state = false;
|
.read(previousChartsTourProvider
|
||||||
|
.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(previousHomeTourProvider
|
||||||
|
.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -988,18 +1065,31 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: locale.languageCode=='ar' ? null:Color(0xFF7DAFBC),
|
color: locale.languageCode == 'ar'
|
||||||
|
? null
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color:locale.languageCode=='ar' ? Colors.white: Color(0xFF7DAFBC), width: 1),
|
color: locale.languageCode == 'ar'
|
||||||
|
? Colors.white
|
||||||
|
: Color(0xFF7DAFBC),
|
||||||
|
width: 1),
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 20,
|
iconSize: 20,
|
||||||
icon: const Icon(Icons.arrow_forward,
|
icon: const Icon(
|
||||||
color: Colors.white,),
|
Icons.arrow_forward,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (locale.languageCode == 'ar') {
|
if (locale.languageCode == 'ar') {
|
||||||
ref.read(previousChartsTourProvider.notifier).state = true;
|
ref
|
||||||
ref.read(previousHomeTourProvider.notifier).state = false;
|
.read(previousChartsTourProvider
|
||||||
|
.notifier)
|
||||||
|
.state = true;
|
||||||
|
ref
|
||||||
|
.read(previousHomeTourProvider
|
||||||
|
.notifier)
|
||||||
|
.state = false;
|
||||||
tutorialCoachMark.finish();
|
tutorialCoachMark.finish();
|
||||||
} else {
|
} else {
|
||||||
tutorialCoachMark.previous();
|
tutorialCoachMark.previous();
|
||||||
@ -1217,6 +1307,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
for (var chart in data) {
|
for (var chart in data) {
|
||||||
final groupBy = chart['group_by'];
|
final groupBy = chart['group_by'];
|
||||||
List response = chart['response'] ?? [];
|
List response = chart['response'] ?? [];
|
||||||
|
final chartHeading = chart['chart_heading'];
|
||||||
|
|
||||||
// Filter the response based on selected filters
|
// Filter the response based on selected filters
|
||||||
var chartFilteredData = response.where((responseItem) {
|
var chartFilteredData = response.where((responseItem) {
|
||||||
@ -1243,6 +1334,26 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
});
|
});
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
|
print('chartFilteredData- $chartFilteredData');
|
||||||
|
|
||||||
|
// If chartFilteredData is empty, print the message
|
||||||
|
if (chartFilteredData.isEmpty) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
print(
|
||||||
|
"Selected year: ${selectedFilters.firstWhere((f) => f['filter_key'] == 'TIME_PERIOD', orElse: () => {
|
||||||
|
'filter_data': ['Unknown']
|
||||||
|
})['filter_data']} - No data for chart: : $chartHeading");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the complete chart data to the filteredData list
|
||||||
|
filteredData.add({
|
||||||
|
...chart,
|
||||||
|
'response': response, // Return full unfiltered response
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// If any data matches the filter, add the whole chart data object
|
// If any data matches the filter, add the whole chart data object
|
||||||
// Add filtered chart only once
|
// Add filtered chart only once
|
||||||
if (chartFilteredData.isNotEmpty &&
|
if (chartFilteredData.isNotEmpty &&
|
||||||
@ -1996,6 +2107,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
color: isBookmarked
|
color: isBookmarked
|
||||||
? Colors.black
|
? Colors.black
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
|
size: 23,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -2015,7 +2127,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 6),
|
||||||
Stack(
|
Stack(
|
||||||
children: [
|
children: [
|
||||||
// Image.asset(
|
// Image.asset(
|
||||||
@ -2031,7 +2143,6 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
// height: 24,
|
// height: 24,
|
||||||
// ),
|
// ),
|
||||||
|
|
||||||
|
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
UaeNumbersAssetPath.share,
|
UaeNumbersAssetPath.share,
|
||||||
semanticsLabel: 'share',
|
semanticsLabel: 'share',
|
||||||
@ -2056,6 +2167,8 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
SizedBox(width: 10),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showRightSideModal(
|
showRightSideModal(
|
||||||
@ -2233,9 +2346,11 @@ 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(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white, // Move color inside BoxDecoration
|
color: Colors
|
||||||
borderRadius: BorderRadius.circular(12), // Ensure border radius is applied
|
.white, // Move color inside BoxDecoration
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
12), // Ensure border radius is applied
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -2280,20 +2395,22 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Flexible(
|
Flexible(
|
||||||
fit: FlexFit.loose,
|
fit: FlexFit.loose,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 20.0,
|
height: 20.0,
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
'(${response[0]['display_value'] ?? 'NA'})',
|
'(${response[0]['display_value'] ?? 'NA'})',
|
||||||
// '(${data['firstYear'] ??
|
// '(${data['firstYear'] ??
|
||||||
// 'NA'} - ${data['lastYear'] ??
|
// 'NA'} - ${data['lastYear'] ??
|
||||||
// 'NA'})',
|
// 'NA'})',
|
||||||
style: const TextStyle(
|
style:
|
||||||
fontSize: 10,
|
const TextStyle(
|
||||||
color: Colors.grey),
|
fontSize: 10,
|
||||||
|
color: Colors
|
||||||
|
.grey),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 1),
|
const SizedBox(height: 1),
|
||||||
Flexible(
|
Flexible(
|
||||||
@ -2302,20 +2419,60 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
height: 50.0,
|
height: 50.0,
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
child: Text(
|
child: Row(
|
||||||
response[0]
|
children: [
|
||||||
['value'] ??
|
Text(
|
||||||
'NA',
|
response[0][
|
||||||
// '${data['roundedAverage'] ??
|
'value'] ??
|
||||||
// 'NA'}',
|
'NA',
|
||||||
style:
|
// '${data['roundedAverage'] ??
|
||||||
const TextStyle(
|
// 'NA'}',
|
||||||
fontSize: 20,
|
style: TextStyle(
|
||||||
fontWeight:
|
fontSize: 20,
|
||||||
FontWeight.w900,
|
fontWeight:
|
||||||
color: Color(
|
FontWeight
|
||||||
0xFF90B0D5),
|
.w900,
|
||||||
),
|
color: response[0]
|
||||||
|
[
|
||||||
|
'calculation'] ==
|
||||||
|
'different'
|
||||||
|
? _getColorFromHex(
|
||||||
|
response[0]
|
||||||
|
[
|
||||||
|
'font_color'])
|
||||||
|
: const Color(
|
||||||
|
0xFF90B0D5),
|
||||||
|
// color: Color(
|
||||||
|
// 0xFF90B0D5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width:
|
||||||
|
1), // Space between text and icon
|
||||||
|
if (response[0][
|
||||||
|
'calculation'] ==
|
||||||
|
'different') ...[
|
||||||
|
if (response[0][
|
||||||
|
'font_color'] ==
|
||||||
|
'#D83731')
|
||||||
|
const Icon(
|
||||||
|
Icons
|
||||||
|
.arrow_downward,
|
||||||
|
color: Colors
|
||||||
|
.red,
|
||||||
|
size: 22)
|
||||||
|
else if (response[
|
||||||
|
0][
|
||||||
|
'font_color'] ==
|
||||||
|
'#11AF22')
|
||||||
|
const Icon(
|
||||||
|
Icons
|
||||||
|
.arrow_upward,
|
||||||
|
color: Colors
|
||||||
|
.green,
|
||||||
|
size: 22),
|
||||||
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -2352,8 +2509,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
height: cardHeight,
|
height: cardHeight,
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white, // Move color inside BoxDecoration
|
color: Colors
|
||||||
borderRadius: BorderRadius.circular(12), // Ensure border radius is applied
|
.white, // Move color inside BoxDecoration
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
12), // Ensure border radius is applied
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize
|
mainAxisSize: MainAxisSize
|
||||||
@ -2424,12 +2583,18 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
// data['lastYearValue']),
|
// data['lastYearValue']),
|
||||||
// apiService.formatAmount(
|
// apiService.formatAmount(
|
||||||
// data['lastYearValue']),
|
// data['lastYearValue']),
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w900,
|
FontWeight.w900,
|
||||||
color:
|
color: response[0][
|
||||||
Color(0xFF90B0D5),
|
'calculation'] ==
|
||||||
|
'different'
|
||||||
|
? _getColorFromHex(
|
||||||
|
response[0][
|
||||||
|
'font_color'])
|
||||||
|
: const Color(
|
||||||
|
0xFF90B0D5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -2452,12 +2617,18 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
'NA',
|
'NA',
|
||||||
// apiService.formatAmount(
|
// apiService.formatAmount(
|
||||||
// data['secondLastYearValue']),
|
// data['secondLastYearValue']),
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w600,
|
FontWeight.w600,
|
||||||
color:
|
color: response[1][
|
||||||
Color(0xFFD83731),
|
'calculation'] ==
|
||||||
|
'different'
|
||||||
|
? _getColorFromHex(
|
||||||
|
response[0][
|
||||||
|
'font_color'])
|
||||||
|
: const Color(
|
||||||
|
0xFFD83731),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -2487,47 +2658,48 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.all(10),
|
margin: const EdgeInsets.all(10),
|
||||||
child: Container(
|
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(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// ConstrainedBox
|
||||||
|
Container(
|
||||||
|
// constraints: const BoxConstraints(
|
||||||
|
// minHeight:
|
||||||
|
// 200, // Minimum height
|
||||||
|
// maxHeight:
|
||||||
|
// 400, // Maximum height
|
||||||
|
// ),
|
||||||
|
height: 350,
|
||||||
|
|
||||||
|
// child: buildChart(chartsData[index]),
|
||||||
decoration: BoxDecoration(
|
child: ChartWidget(
|
||||||
border: Border.all(
|
chartData:
|
||||||
color: Color(int.parse((chartScreenData[
|
chartsData[index]))
|
||||||
'border_color'] ?? '#898C81')
|
],
|
||||||
.replaceFirst('#', '0xff'),),), // Border color
|
),
|
||||||
width: 1, // Border width
|
),
|
||||||
),
|
));
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(8), // Optional: Rounded corners
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
|
|
||||||
// ConstrainedBox
|
|
||||||
Container
|
|
||||||
(
|
|
||||||
// constraints: const BoxConstraints(
|
|
||||||
// minHeight:
|
|
||||||
// 200, // Minimum height
|
|
||||||
// maxHeight:
|
|
||||||
// 400, // Maximum height
|
|
||||||
// ),
|
|
||||||
height: 320,
|
|
||||||
|
|
||||||
// child: buildChart(chartsData[index]),
|
|
||||||
child: ChartWidget(
|
|
||||||
chartData:
|
|
||||||
chartsData[index]))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -2597,3 +2769,12 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to convert hex color string to Color
|
||||||
|
Color _getColorFromHex(String hexColor) {
|
||||||
|
hexColor = hexColor.replaceFirst('#', '');
|
||||||
|
if (hexColor.length == 6) {
|
||||||
|
hexColor = 'FF$hexColor'; // Add alpha if not provided
|
||||||
|
}
|
||||||
|
return Color(int.parse(hexColor, radix: 16));
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
@ -48,8 +49,11 @@ class ChartWidget extends StatelessWidget {
|
|||||||
List<PieChartSectionData> parsePieChartData(
|
List<PieChartSectionData> parsePieChartData(
|
||||||
dynamic chartData,
|
dynamic chartData,
|
||||||
double totalValue,
|
double totalValue,
|
||||||
|
// String totalValue,
|
||||||
int? touchedIndex,
|
int? touchedIndex,
|
||||||
) {
|
) {
|
||||||
|
debugPrint('Chart Data: ${jsonEncode(chartData)}');
|
||||||
|
|
||||||
return chartData['response']
|
return chartData['response']
|
||||||
.asMap()
|
.asMap()
|
||||||
.entries
|
.entries
|
||||||
@ -69,27 +73,54 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// Handle different types: int, double, and String
|
// Handle different types: int, double, and String
|
||||||
double value = 0.0;
|
double value = 0.0;
|
||||||
|
|
||||||
if (data['ObsValue']['Value'] is String) {
|
var rawValue = data['ObsValue']['Value'];
|
||||||
value = double.tryParse(data['ObsValue']['Value']) ?? 0.0; // Parse string to double
|
|
||||||
} else if (data['ObsValue']['Value'] is int) {
|
print('Raw Value: $rawValue (Type: ${rawValue.runtimeType})');
|
||||||
value = (data['ObsValue']['Value'] as int).toDouble(); // Convert int to double
|
|
||||||
} else if (data['ObsValue']['Value'] is double) {
|
if (rawValue is String) {
|
||||||
value = data['ObsValue']['Value']; // Already a double
|
value = double.tryParse(rawValue) ?? 0.0;
|
||||||
|
} else if (rawValue is int) {
|
||||||
|
value = rawValue.toDouble();
|
||||||
|
} else if (rawValue is double) {
|
||||||
|
value = rawValue;
|
||||||
|
} else {
|
||||||
|
print('Unexpected Type for ObsValue[Value]: ${rawValue.runtimeType}');
|
||||||
}
|
}
|
||||||
|
|
||||||
print('piePArse1 - $value');
|
// if (data['ObsValue']['Value'] is String) {
|
||||||
double percentage = (value / totalValue) * 100;
|
// 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;
|
||||||
|
double percentage = (totalValue > 0) ? (value / totalValue) * 100 : 0.0;
|
||||||
|
if (kDebugMode) {
|
||||||
|
print('percentage- $percentage');
|
||||||
|
print('Total Value: $totalValue');
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('debug Total Value- $totalValue');
|
||||||
|
debugPrint('debug percentage- $percentage');
|
||||||
bool isTouched = index == touchedIndex;
|
bool isTouched = index == touchedIndex;
|
||||||
|
|
||||||
return PieChartSectionData(
|
return PieChartSectionData(
|
||||||
value: value,
|
value: value,
|
||||||
color: Colors.primaries[index % Colors.primaries.length],
|
color: Colors.primaries[index % Colors.primaries.length],
|
||||||
title: '${percentage.toStringAsFixed(1)}%',
|
title: '${percentage.toStringAsFixed(1)}%',
|
||||||
radius: isTouched ? 60 : 50, // Increase size when touched
|
radius: isTouched ? 60 : 50,
|
||||||
|
|
||||||
|
// Increase size when touched
|
||||||
titleStyle: TextStyle(
|
titleStyle: TextStyle(
|
||||||
fontSize: isTouched ? 12 : 10,
|
fontSize: isTouched ? 12 : 10,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white,
|
color: Colors.black,
|
||||||
|
// color: Colors.white,
|
||||||
),
|
),
|
||||||
|
titlePositionPercentageOffset: 1.3,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
@ -116,21 +147,33 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
TooltipTheme(
|
TooltipTheme(
|
||||||
data: TooltipThemeData(
|
data: TooltipThemeData(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blueGrey[800], // Change background color
|
color: Colors.blueGrey[800], // Change background color
|
||||||
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
borderRadius:
|
||||||
),
|
BorderRadius.circular(8), // Optional: rounded corners
|
||||||
textStyle: TextStyle(color: Colors.white), // Change text color
|
),
|
||||||
),
|
textStyle: TextStyle(color: Colors.white), // Change text color
|
||||||
child: Tooltip(
|
|
||||||
message: title, // Full text on hover
|
|
||||||
child: Text(
|
|
||||||
shortTitle,
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
|
|
||||||
),
|
),
|
||||||
),),
|
child: Tooltip(
|
||||||
|
message: title, // Full text on hover
|
||||||
|
child: ConstrainedBox(
|
||||||
|
// Constrain width to allow wrapping
|
||||||
|
constraints: BoxConstraints(maxWidth: 100),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow:
|
||||||
|
TextOverflow.ellipsis, // Ensures text doesn't overflow
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 5),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -152,6 +195,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
return Center(child: Text('No chart data available'));
|
return Center(child: Text('No chart data available'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print(chartData['chart_type_json']['TIME_PERIOD']);
|
||||||
|
|
||||||
String groupByKey = chartData['group_by'] ?? '';
|
String groupByKey = chartData['group_by'] ?? '';
|
||||||
print('groupByKey $groupByKey');
|
print('groupByKey $groupByKey');
|
||||||
Set<String> groupByValues = extractGroupByValues(chartData, groupByKey);
|
Set<String> groupByValues = extractGroupByValues(chartData, groupByKey);
|
||||||
@ -242,13 +287,28 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
case 'pie_chart':
|
case 'pie_chart':
|
||||||
double totalValue = chartData['response']
|
double totalValue = chartData['response'].map<double>((entry) {
|
||||||
.map<double>((entry) {
|
|
||||||
var value = entry['ObsValue']['Value'];
|
var value = entry['ObsValue']['Value'];
|
||||||
print('Processing value: $value, type: ${value.runtimeType}'); // Debug each value
|
print(
|
||||||
return value is int ? value.toDouble() : value is String ? double.tryParse(value) ?? 0.0 : 0.0;
|
'Processing value: $value, type: ${value.runtimeType}'); // Debug each value
|
||||||
})
|
print(value is int
|
||||||
.fold(0.0, (prev, element) => prev + element);
|
? value.toDouble()
|
||||||
|
: value is String
|
||||||
|
? double.tryParse(value) ?? 0.0
|
||||||
|
: 0.0);
|
||||||
|
return (value is num)
|
||||||
|
? value.toDouble()
|
||||||
|
: value is String
|
||||||
|
? double.tryParse(value) ?? 0.0
|
||||||
|
: 0.0;
|
||||||
|
}).fold(0.0, (prev, element) => prev + element);
|
||||||
|
// List<String> totalValues = chartData['response']
|
||||||
|
// .map<String>((entry) {
|
||||||
|
// var value = entry['ObsValue']['Value'];
|
||||||
|
// print('Processing value: $value, type: ${value.runtimeType}'); // Debug each value
|
||||||
|
//
|
||||||
|
// return value.toString(); // Convert to string
|
||||||
|
// }).fold(0.0, (prev, element) => prev + element);
|
||||||
|
|
||||||
ValueNotifier<int?> touchedIndex = ValueNotifier(null);
|
ValueNotifier<int?> touchedIndex = ValueNotifier(null);
|
||||||
|
|
||||||
@ -263,7 +323,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
SizedBox(height: 5),
|
SizedBox(height: 15),
|
||||||
Text(
|
Text(
|
||||||
chartData['chart_sub_heading'] ?? '',
|
chartData['chart_sub_heading'] ?? '',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -272,8 +332,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
SizedBox(height: 40),
|
SizedBox(height: 70),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ValueListenableBuilder<int?>(
|
child: ValueListenableBuilder<int?>(
|
||||||
valueListenable: touchedIndex,
|
valueListenable: touchedIndex,
|
||||||
@ -299,30 +358,33 @@ class ChartWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height:60),
|
SizedBox(height: 65),
|
||||||
Flexible(
|
Flexible(
|
||||||
|
// child: SingleChildScrollView(
|
||||||
|
// scrollDirection: Axis.horizontal,
|
||||||
|
//
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Container(
|
child: Container(
|
||||||
// constraints:
|
constraints:
|
||||||
// BoxConstraints(minHeight: 5), // Allow dynamic height
|
BoxConstraints(minHeight: 3), // Allow dynamic height
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 0.0, right: 0.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']),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// ),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -372,11 +434,11 @@ class ChartWidget extends StatelessWidget {
|
|||||||
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
|
tooltipPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 4, vertical: 8), // Optional
|
||||||
tooltipHorizontalAlignment: FLHorizontalAlignment.left,
|
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
|
||||||
@ -534,7 +596,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
colorIndex % uniqueColorsLine_trend_2.length];
|
colorIndex % uniqueColorsLine_trend_2.length];
|
||||||
colorIndex++;
|
colorIndex++;
|
||||||
}
|
}
|
||||||
print('LnTrnd1');
|
print('LnTrnd1');
|
||||||
|
|
||||||
// Extract all years from the chart data
|
// Extract all years from the chart data
|
||||||
List<int> years = (chartData['response'] as List<dynamic>)
|
List<int> years = (chartData['response'] as List<dynamic>)
|
||||||
@ -571,10 +633,9 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']))
|
// (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']))
|
||||||
// .toSet();
|
// .toSet();
|
||||||
|
|
||||||
|
Set<String> uniqueXValues = filteredData.map<String>((entry) {
|
||||||
Set<String> uniqueXValues = filteredData
|
String? timePeriod =
|
||||||
.map<String>((entry) {
|
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) {
|
||||||
@ -596,8 +657,7 @@ class ChartWidget extends StatelessWidget {
|
|||||||
print('Unknown format: $timePeriod');
|
print('Unknown format: $timePeriod');
|
||||||
return timePeriod; // Keep it as is
|
return timePeriod; // Keep it as is
|
||||||
}
|
}
|
||||||
})
|
}).toSet();
|
||||||
.toSet();
|
|
||||||
|
|
||||||
print("Unique X Values: $uniqueXValues");
|
print("Unique X Values: $uniqueXValues");
|
||||||
|
|
||||||
@ -606,18 +666,30 @@ class ChartWidget extends StatelessWidget {
|
|||||||
if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) {
|
if (RegExp(r'^\d{4}$').hasMatch(timePeriod)) {
|
||||||
return double.parse(timePeriod); // Year-only (2019 → 2019.0)
|
return double.parse(timePeriod); // Year-only (2019 → 2019.0)
|
||||||
} else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) {
|
} else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) {
|
||||||
return double.parse(timePeriod.replaceAll('-', '.')); // Year-Month (2019-11 → 2019.11)
|
return double.parse(timePeriod.replaceAll(
|
||||||
|
'-', '.')); // Year-Month (2019-11 → 2019.11)
|
||||||
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
|
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
|
||||||
// Year-MonthAbbr (2019-Nov)
|
// Year-MonthAbbr (2019-Nov)
|
||||||
Map<String, int> monthMap = {
|
Map<String, int> monthMap = {
|
||||||
'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
|
'Jan': 1,
|
||||||
'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
|
'Feb': 2,
|
||||||
'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
|
'Mar': 3,
|
||||||
|
'Apr': 4,
|
||||||
|
'May': 5,
|
||||||
|
'Jun': 6,
|
||||||
|
'Jul': 7,
|
||||||
|
'Aug': 8,
|
||||||
|
'Sep': 9,
|
||||||
|
'Oct': 10,
|
||||||
|
'Nov': 11,
|
||||||
|
'Dec': 12
|
||||||
};
|
};
|
||||||
|
|
||||||
List<String> parts = timePeriod.split('-');
|
List<String> parts = timePeriod.split('-');
|
||||||
int month = monthMap[parts[1]] ?? 1; // Default to January if unknown
|
int month =
|
||||||
return double.parse('${parts[0]}.$month'); // Convert to format (2019-Nov → 2019.11)
|
monthMap[parts[1]] ?? 1; // Default to January if unknown
|
||||||
|
return double.parse(
|
||||||
|
'${parts[0]}.$month'); // Convert to format (2019-Nov → 2019.11)
|
||||||
}
|
}
|
||||||
|
|
||||||
throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
|
throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
|
||||||
@ -629,15 +701,12 @@ class ChartWidget extends StatelessWidget {
|
|||||||
.toSet();
|
.toSet();
|
||||||
print('Processed X Values: $uniqueXValuesProcessed');
|
print('Processed X Values: $uniqueXValuesProcessed');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print('LnTrnd2.1');
|
print('LnTrnd2.1');
|
||||||
|
|
||||||
// Generate line bars for the chart
|
// Generate line bars for the chart
|
||||||
List<LineChartBarData> lineBars =
|
List<LineChartBarData> lineBars =
|
||||||
lineBarsData(filteredData, groupByValues, groupByKey);
|
lineBarsData(filteredData, groupByValues, groupByKey);
|
||||||
|
|
||||||
|
|
||||||
print('LnTrnd3');
|
print('LnTrnd3');
|
||||||
|
|
||||||
return Column(children: [
|
return Column(children: [
|
||||||
@ -671,10 +740,9 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
|
// minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
|
||||||
// maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
|
// maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
|
||||||
|
|
||||||
|
// minX: uniqueXValuesProcessed.reduce((a, b) => a < b ? a : b),
|
||||||
// minX: uniqueXValuesProcessed.reduce((a, b) => a < b ? a : b),
|
// maxX: uniqueXValuesProcessed.reduce((a, b) => a > b ? a : b),
|
||||||
// maxX: uniqueXValuesProcessed.reduce((a, b) => a > b ? a : b),
|
))),
|
||||||
))),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
@ -924,11 +992,61 @@ class ChartWidget extends StatelessWidget {
|
|||||||
List<String> xAxisData = [];
|
List<String> xAxisData = [];
|
||||||
List<double> yAxisData = [];
|
List<double> yAxisData = [];
|
||||||
|
|
||||||
|
var xadditionalgrp = chartData['chart_type_json']['additional_x_group'];
|
||||||
|
|
||||||
|
print('xadditionalgrp-$xadditionalgrp');
|
||||||
|
|
||||||
for (var entry in chartData['response']) {
|
for (var entry in chartData['response']) {
|
||||||
var xValue = entry['ObsKey'][groupByKey];
|
var xValue = entry['ObsKey'][groupByKey];
|
||||||
|
var xTimePeriod = entry['ObsKey']['TIME_PERIOD'];
|
||||||
var yValue = entry['ObsValue']['Value'];
|
var yValue = entry['ObsValue']['Value'];
|
||||||
|
var xadditionalgroup =
|
||||||
|
chartData['chart_type_json']['additional_x_group'];
|
||||||
|
|
||||||
|
print('chartData response: ${chartData['response']}');
|
||||||
|
|
||||||
|
print('xValue-$xValue');
|
||||||
|
print('Xadditionalt-$xTimePeriod');
|
||||||
|
print('xadditionalgroup-$xadditionalgroup');
|
||||||
|
print('yValue-$yValue');
|
||||||
|
|
||||||
|
if (xadditionalgrp == 'TIME_PERIOD') {
|
||||||
|
chartData['response'].sort((a, b) {
|
||||||
|
// Convert TIME_PERIOD to int for proper sorting
|
||||||
|
int timeA =
|
||||||
|
int.tryParse(a['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
|
||||||
|
int timeB =
|
||||||
|
int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
|
||||||
|
|
||||||
|
// Extract QUARTER and convert "Q1", "Q2", etc. to numeric values
|
||||||
|
int quarterA = int.tryParse(
|
||||||
|
a['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ??
|
||||||
|
0;
|
||||||
|
int quarterB = int.tryParse(
|
||||||
|
b['ObsKey']['QUARTER'].toString().replaceAll('Q', '')) ??
|
||||||
|
0;
|
||||||
|
|
||||||
|
// First, sort by TIME_PERIOD. If equal, sort by QUARTER
|
||||||
|
if (timeA != timeB) {
|
||||||
|
return timeA.compareTo(timeB);
|
||||||
|
} else {
|
||||||
|
return quarterA.compareTo(quarterB);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (xValue != null && yValue != null) {
|
||||||
|
// xAxisData.add(xValue.toString());
|
||||||
|
// yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
|
||||||
|
// }
|
||||||
if (xValue != null && yValue != null) {
|
if (xValue != null && yValue != null) {
|
||||||
xAxisData.add(xValue.toString());
|
// Check if additional_x_group is "Timeperiod" and concatenate
|
||||||
|
String xLabel = xValue.toString();
|
||||||
|
if (xadditionalgroup == 'TIME_PERIOD' && xTimePeriod != null) {
|
||||||
|
xLabel = '$xTimePeriod-$xValue'; // Format: Label (TimePeriod)
|
||||||
|
}
|
||||||
|
|
||||||
|
xAxisData.add(xLabel);
|
||||||
yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
|
yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -959,7 +1077,7 @@ 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(
|
barTouchData: BarTouchData(
|
||||||
enabled: true,
|
enabled: true,
|
||||||
handleBuiltInTouches: true,
|
handleBuiltInTouches: true,
|
||||||
@ -1004,7 +1122,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
: title;
|
: title;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0,left: 25.0),
|
padding:
|
||||||
|
const EdgeInsets.only(top: 8.0, left: 55.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(
|
||||||
@ -1012,36 +1131,43 @@ class ChartWidget extends StatelessWidget {
|
|||||||
angle: -1.5,
|
angle: -1.5,
|
||||||
|
|
||||||
child: TooltipTheme(
|
child: TooltipTheme(
|
||||||
data: TooltipThemeData(
|
data: TooltipThemeData(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blueGrey[800], // Change background color
|
color: Colors.blueGrey[
|
||||||
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
800], // Change background color
|
||||||
),
|
borderRadius: BorderRadius.circular(
|
||||||
textStyle: TextStyle(color: Colors.white), // Change text color
|
8), // Optional: rounded corners
|
||||||
),
|
),
|
||||||
|
textStyle: TextStyle(
|
||||||
|
color: Colors
|
||||||
|
.white), // Change text color
|
||||||
|
),
|
||||||
child: TooltipTheme(
|
child: TooltipTheme(
|
||||||
data: TooltipThemeData(
|
data: TooltipThemeData(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blueGrey[800], // Change background color
|
color: Colors.blueGrey[
|
||||||
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
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(
|
||||||
|
// title,
|
||||||
|
displayTitle,
|
||||||
|
softWrap: true,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
textStyle: TextStyle(color: Colors.white), // Change text color
|
|
||||||
),
|
),
|
||||||
child: Tooltip(
|
|
||||||
message: title,
|
|
||||||
|
|
||||||
child: Text(
|
|
||||||
// title,
|
|
||||||
displayTitle,
|
|
||||||
softWrap: true,
|
|
||||||
style: TextStyle(fontSize: 10,),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
return Container();
|
return Container();
|
||||||
@ -1111,102 +1237,104 @@ class ChartWidget extends StatelessWidget {
|
|||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
// Chart
|
// Chart
|
||||||
Expanded(
|
Expanded(
|
||||||
child: BarChart(
|
child: BarChart(
|
||||||
BarChartData(
|
BarChartData(
|
||||||
alignment: BarChartAlignment.spaceAround,
|
alignment: BarChartAlignment.spaceAround,
|
||||||
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,
|
||||||
rotationQuarterTurns: rotationTurns,
|
rotationQuarterTurns: rotationTurns,
|
||||||
barTouchData: BarTouchData(
|
barTouchData: BarTouchData(
|
||||||
enabled: true,
|
enabled: true,
|
||||||
handleBuiltInTouches: true,
|
handleBuiltInTouches: true,
|
||||||
touchTooltipData: BarTouchTooltipData(
|
touchTooltipData: BarTouchTooltipData(
|
||||||
fitInsideHorizontally: true,
|
fitInsideHorizontally: true,
|
||||||
fitInsideVertically: true,
|
fitInsideVertically: true,
|
||||||
tooltipPadding: const EdgeInsets.all(8),
|
tooltipPadding: const EdgeInsets.all(8),
|
||||||
tooltipMargin: 16,
|
tooltipMargin: 16,
|
||||||
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
getTooltipItem: (group, groupIndex, rod, rodIndex) {
|
||||||
return BarTooltipItem(
|
return BarTooltipItem(
|
||||||
'${rod.toY.toStringAsFixed(1)}',
|
'${rod.toY.toStringAsFixed(1)}',
|
||||||
const TextStyle(color: Colors.white),
|
const TextStyle(color: Colors.white),
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
titlesData: FlTitlesData(
|
|
||||||
leftTitles: AxisTitles(
|
|
||||||
sideTitles: SideTitles(
|
|
||||||
showTitles: false,
|
|
||||||
interval: (yAxisData.isNotEmpty
|
|
||||||
? yAxisData.reduce((a, b) => a > b ? a : b) / 5
|
|
||||||
: 1),
|
|
||||||
getTitlesWidget: (value, meta) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 8.0),
|
|
||||||
child: Text('${value.toInt()}'),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
reservedSize: 60,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomTitles: AxisTitles(
|
titlesData: FlTitlesData(
|
||||||
sideTitles: SideTitles(
|
leftTitles: AxisTitles(
|
||||||
showTitles: true,
|
sideTitles: SideTitles(
|
||||||
getTitlesWidget: (value, meta) {
|
showTitles: false,
|
||||||
if (value.toInt() < xAxisData.length) {
|
interval: (yAxisData.isNotEmpty
|
||||||
|
? yAxisData.reduce((a, b) => a > b ? a : b) / 5
|
||||||
|
: 1),
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: Transform.rotate(
|
child: Text('${value.toInt()}'),
|
||||||
angle: -1.58,
|
);
|
||||||
// angle: -45 *
|
},
|
||||||
// (3.1415927 / 180), // Rotating by -45 degrees
|
reservedSize: 60,
|
||||||
alignment: Alignment.center,
|
),
|
||||||
child: Center(
|
),
|
||||||
child: SizedBox(
|
bottomTitles: AxisTitles(
|
||||||
width: 100,
|
sideTitles: SideTitles(
|
||||||
child: Text(
|
showTitles: true,
|
||||||
xAxisData[value.toInt()],
|
getTitlesWidget: (value, meta) {
|
||||||
style: const TextStyle(fontSize: 12),
|
if (value.toInt() < xAxisData.length) {
|
||||||
softWrap: true,
|
return Padding(
|
||||||
maxLines: 3,
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Transform.rotate(
|
||||||
|
angle: -1.58,
|
||||||
|
// angle: -45 *
|
||||||
|
// (3.1415927 / 180), // Rotating by -45 degrees
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 100,
|
||||||
|
child: Text(
|
||||||
|
xAxisData[value.toInt()],
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 3,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
return Container();
|
||||||
return Container();
|
},
|
||||||
},
|
reservedSize: 85,
|
||||||
reservedSize: 85,
|
),
|
||||||
|
),
|
||||||
|
topTitles: AxisTitles(
|
||||||
|
sideTitles:
|
||||||
|
SideTitles(showTitles: false), // Hide top titles
|
||||||
|
),
|
||||||
|
rightTitles: AxisTitles(
|
||||||
|
sideTitles:
|
||||||
|
SideTitles(showTitles: false), // Hide right titles
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
topTitles: AxisTitles(
|
gridData: FlGridData(show: false),
|
||||||
sideTitles: SideTitles(showTitles: false), // Hide top titles
|
borderData: FlBorderData(show: false),
|
||||||
),
|
barGroups: List.generate(
|
||||||
rightTitles: AxisTitles(
|
xAxisData.length,
|
||||||
sideTitles:
|
(index) => BarChartGroupData(
|
||||||
SideTitles(showTitles: false), // Hide right titles
|
x: index,
|
||||||
),
|
barRods: [
|
||||||
),
|
BarChartRodData(
|
||||||
gridData: FlGridData(show: false),
|
toY: yAxisData[index],
|
||||||
borderData: FlBorderData(show: false),
|
color: Colors.blueAccent,
|
||||||
barGroups: List.generate(
|
borderRadius: BorderRadius.circular(4),
|
||||||
xAxisData.length,
|
width: 20,
|
||||||
(index) => BarChartGroupData(
|
),
|
||||||
x: index,
|
],
|
||||||
barRods: [
|
),
|
||||||
BarChartRodData(
|
|
||||||
toY: yAxisData[index],
|
|
||||||
color: Colors.blueAccent,
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
width: 20,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
))
|
),
|
||||||
]);
|
]);
|
||||||
case 'fl_multi_bar':
|
case 'fl_multi_bar':
|
||||||
double _calculateChartWidth(dynamic chartData) {
|
double _calculateChartWidth(dynamic chartData) {
|
||||||
@ -1218,14 +1346,10 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// Group crops by CROP_TYPE
|
// Group crops by CROP_TYPE
|
||||||
Map<String, List<String>> groupedCrops = {};
|
Map<String, List<String>> groupedCrops = {};
|
||||||
|
|
||||||
|
|
||||||
int touchedGroupIndex = -1;
|
int touchedGroupIndex = -1;
|
||||||
// Iterate over the chartData to group crops by CROP_TYPE
|
// Iterate over the chartData to group crops by CROP_TYPE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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];
|
||||||
@ -1233,7 +1357,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
|
|
||||||
// Use a Set to avoid duplicates
|
// Use a Set to avoid duplicates
|
||||||
if (groupedCrops.containsKey(cropType)) {
|
if (groupedCrops.containsKey(cropType)) {
|
||||||
groupedCrops[cropType] = (groupedCrops[cropType]! + [crop]).toSet().toList();
|
groupedCrops[cropType] =
|
||||||
|
(groupedCrops[cropType]! + [crop]).toSet().toList();
|
||||||
} else {
|
} else {
|
||||||
groupedCrops[cropType] = [crop];
|
groupedCrops[cropType] = [crop];
|
||||||
}
|
}
|
||||||
@ -1255,7 +1380,6 @@ class ChartWidget extends StatelessWidget {
|
|||||||
//
|
//
|
||||||
// print('groupedCropsflmutli- $groupedCrops');
|
// print('groupedCropsflmutli- $groupedCrops');
|
||||||
|
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Text(
|
Text(
|
||||||
@ -1286,8 +1410,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
child: BarChart(
|
child: BarChart(
|
||||||
BarChartData(
|
BarChartData(
|
||||||
alignment: BarChartAlignment.spaceAround,
|
alignment: BarChartAlignment.spaceAround,
|
||||||
maxY:
|
maxY: _calculateMaxY(
|
||||||
_calculateMaxY(chartData), // Dynamically calculate max Y
|
chartData), // Dynamically calculate max Y
|
||||||
barGroups: _buildHorizontalRotateBarGroups(
|
barGroups: _buildHorizontalRotateBarGroups(
|
||||||
chartData, groupByValues), // Build bar groups
|
chartData, groupByValues), // Build bar groups
|
||||||
titlesData: FlTitlesData(
|
titlesData: FlTitlesData(
|
||||||
@ -1310,27 +1434,31 @@ class ChartWidget extends StatelessWidget {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding: const EdgeInsets.only(top: 8.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: TooltipTheme(
|
child: TooltipTheme(
|
||||||
data: TooltipThemeData(
|
data: TooltipThemeData(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blueGrey[800], // Change background color
|
color: Colors.blueGrey[
|
||||||
borderRadius: BorderRadius.circular(8), // Optional: rounded corners
|
800], // Change background color
|
||||||
),
|
borderRadius: BorderRadius.circular(
|
||||||
textStyle: TextStyle(color: Colors.white), // Change text color
|
8), // Optional: rounded corners
|
||||||
),
|
),
|
||||||
child: Tooltip(
|
textStyle: TextStyle(
|
||||||
message: title,
|
color: Colors
|
||||||
child: Text(
|
.white), // Change text color
|
||||||
displayTitle,
|
|
||||||
softWrap: true,
|
|
||||||
// style: TextStyle(backgroundColor: Colors.blueGrey[800]),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
)),
|
|
||||||
|
|
||||||
),
|
),
|
||||||
|
child: Tooltip(
|
||||||
|
message: title,
|
||||||
|
child: Text(
|
||||||
|
displayTitle,
|
||||||
|
softWrap: true,
|
||||||
|
// style: TextStyle(backgroundColor: Colors.blueGrey[800]),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
)),
|
||||||
|
),
|
||||||
)));
|
)));
|
||||||
// return Transform.rotate(
|
// return Transform.rotate(
|
||||||
// angle:
|
// angle:
|
||||||
@ -1353,7 +1481,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
borderData: FlBorderData(show: false),
|
borderData: FlBorderData(show: false),
|
||||||
barTouchData: BarTouchData(
|
barTouchData: BarTouchData(
|
||||||
touchTooltipData: BarTouchTooltipData(
|
touchTooltipData: BarTouchTooltipData(
|
||||||
tooltipHorizontalAlignment: FLHorizontalAlignment.center,
|
tooltipHorizontalAlignment:
|
||||||
|
FLHorizontalAlignment.center,
|
||||||
tooltipRoundedRadius: 8,
|
tooltipRoundedRadius: 8,
|
||||||
fitInsideHorizontally:
|
fitInsideHorizontally:
|
||||||
true, // Ensure it fits within the screen
|
true, // Ensure it fits within the screen
|
||||||
@ -1371,7 +1500,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
groupByValues.elementAt(groupIndex);
|
groupByValues.elementAt(groupIndex);
|
||||||
|
|
||||||
// Fetch the crop for the current group from groupedCrops
|
// Fetch the crop for the current group from groupedCrops
|
||||||
String cropType = groupByValues.elementAt(groupIndex);
|
String cropType =
|
||||||
|
groupByValues.elementAt(groupIndex);
|
||||||
print('GrpcropType: $cropType');
|
print('GrpcropType: $cropType');
|
||||||
// String crop = groupedCrops[cropType]![rodIndex];
|
// String crop = groupedCrops[cropType]![rodIndex];
|
||||||
|
|
||||||
@ -1384,7 +1514,9 @@ class ChartWidget extends StatelessWidget {
|
|||||||
print(
|
print(
|
||||||
'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex');
|
'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex');
|
||||||
// crop = cropType; // Fallback to cropType
|
// crop = cropType; // Fallback to cropType
|
||||||
crop = (crops != null && crops.isNotEmpty) ? crops.first : cropType;
|
crop = (crops != null && crops.isNotEmpty)
|
||||||
|
? crops.first
|
||||||
|
: cropType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print('groupedCrops1: $groupedCrops - $rodIndex');
|
// print('groupedCrops1: $groupedCrops - $rodIndex');
|
||||||
@ -1431,7 +1563,8 @@ class ChartWidget extends StatelessWidget {
|
|||||||
response != null &&
|
response != null &&
|
||||||
response.spot != null) {
|
response.spot != null) {
|
||||||
// setState(() {
|
// setState(() {
|
||||||
touchedGroupIndex = response.spot!.touchedBarGroupIndex;
|
touchedGroupIndex =
|
||||||
|
response.spot!.touchedBarGroupIndex;
|
||||||
// });
|
// });
|
||||||
} else {
|
} else {
|
||||||
// setState(() {
|
// setState(() {
|
||||||
@ -1950,7 +2083,6 @@ class ChartWidget extends StatelessWidget {
|
|||||||
return lineBars;
|
return lineBars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Function to parse TIME_PERIOD into a EXACT value
|
/// Function to parse TIME_PERIOD into a EXACT value
|
||||||
double parseTimePeriod(String timePeriod) {
|
double parseTimePeriod(String timePeriod) {
|
||||||
// Match formats
|
// Match formats
|
||||||
@ -1959,13 +2091,23 @@ class ChartWidget extends StatelessWidget {
|
|||||||
return double.parse(timePeriod); // Year as a double (2020 → 2020.0)
|
return double.parse(timePeriod); // Year as a double (2020 → 2020.0)
|
||||||
} else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) {
|
} else if (RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod)) {
|
||||||
// Format: Year-Month (e.g., "2020-10")
|
// Format: Year-Month (e.g., "2020-10")
|
||||||
return double.parse(timePeriod.replaceAll('-', '.')); // Convert "2020-10" → 2020.10
|
return double.parse(
|
||||||
|
timePeriod.replaceAll('-', '.')); // Convert "2020-10" → 2020.10
|
||||||
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
|
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
|
||||||
// Format: Year-MonthAbbr (e.g., "2020-Oct")
|
// Format: Year-MonthAbbr (e.g., "2020-Oct")
|
||||||
Map<String, int> monthMap = {
|
Map<String, int> monthMap = {
|
||||||
'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4,
|
'Jan': 1,
|
||||||
'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8,
|
'Feb': 2,
|
||||||
'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
|
'Mar': 3,
|
||||||
|
'Apr': 4,
|
||||||
|
'May': 5,
|
||||||
|
'Jun': 6,
|
||||||
|
'Jul': 7,
|
||||||
|
'Aug': 8,
|
||||||
|
'Sep': 9,
|
||||||
|
'Oct': 10,
|
||||||
|
'Nov': 11,
|
||||||
|
'Dec': 12
|
||||||
};
|
};
|
||||||
|
|
||||||
List<String> parts = timePeriod.split('-');
|
List<String> parts = timePeriod.split('-');
|
||||||
@ -1977,7 +2119,6 @@ class ChartWidget extends StatelessWidget {
|
|||||||
throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
|
throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<LineChartBarData> lineBarsData(List<dynamic> filteredData,
|
List<LineChartBarData> lineBarsData(List<dynamic> filteredData,
|
||||||
Set<String> groupByValues, String groupByKey) {
|
Set<String> groupByValues, String groupByKey) {
|
||||||
List<LineChartBarData> lineBars = [];
|
List<LineChartBarData> lineBars = [];
|
||||||
@ -2042,9 +2183,6 @@ class ChartWidget extends StatelessWidget {
|
|||||||
|
|
||||||
print('spots - $spots');
|
print('spots - $spots');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// List<FlSpot> spots = filteredData
|
// List<FlSpot> spots = filteredData
|
||||||
// .where((entry) => entry['ObsKey'][groupByKey] == group)
|
// .where((entry) => entry['ObsKey'][groupByKey] == group)
|
||||||
// .map<FlSpot>((entry) {
|
// .map<FlSpot>((entry) {
|
||||||
@ -2060,8 +2198,6 @@ class ChartWidget extends StatelessWidget {
|
|||||||
// return FlSpot(xValue, yValue);
|
// return FlSpot(xValue, yValue);
|
||||||
// }).toList();
|
// }).toList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print('lineGrp2');
|
print('lineGrp2');
|
||||||
// Add a line for this group
|
// Add a line for this group
|
||||||
lineBars.add(
|
lineBars.add(
|
||||||
@ -2106,11 +2242,11 @@ class ChartWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FlTitlesData titlesData1(Set<double> xValues) {
|
FlTitlesData titlesData1(Set<double> xValues) {
|
||||||
|
|
||||||
print('tileDATa1xvalue - $xValues');
|
print('tileDATa1xvalue - $xValues');
|
||||||
|
|
||||||
double findClosest(double value, Set<double> values) {
|
double findClosest(double value, Set<double> values) {
|
||||||
return values.reduce((a, b) => (value - a).abs() < (value - b).abs() ? a : b);
|
return values
|
||||||
|
.reduce((a, b) => (value - a).abs() < (value - b).abs() ? a : b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FlTitlesData(
|
return FlTitlesData(
|
||||||
@ -2123,8 +2259,14 @@ class ChartWidget extends StatelessWidget {
|
|||||||
String formattedValue;
|
String formattedValue;
|
||||||
|
|
||||||
if (value % 10 == 0) {
|
if (value % 10 == 0) {
|
||||||
// Check if the value is in the millions or thousands range
|
// Check if the value is in the millions or thousands range
|
||||||
if (value >= 1000000) {
|
|
||||||
|
if (value >= 1000000000000) {
|
||||||
|
formattedValue =
|
||||||
|
'${(value / 1000000000000).toStringAsFixed(0)}T';
|
||||||
|
} else if (value >= 1000000000) {
|
||||||
|
formattedValue = '${(value / 1000000000).toStringAsFixed(0)}B';
|
||||||
|
} else if (value >= 1000000) {
|
||||||
formattedValue = '${(value / 1000000).toStringAsFixed(0)}M';
|
formattedValue = '${(value / 1000000).toStringAsFixed(0)}M';
|
||||||
} else if (value >= 1000) {
|
} else if (value >= 1000) {
|
||||||
formattedValue = '${(value / 1000).toStringAsFixed(0)}k';
|
formattedValue = '${(value / 1000).toStringAsFixed(0)}k';
|
||||||
@ -2158,21 +2300,22 @@ class ChartWidget extends StatelessWidget {
|
|||||||
interval: null,
|
interval: null,
|
||||||
// interval: 10, // Ensure each year is shown only once
|
// interval: 10, // Ensure each year is shown only once
|
||||||
getTitlesWidget: (value, meta) {
|
getTitlesWidget: (value, meta) {
|
||||||
|
|
||||||
print('BtmTiles :-$value');
|
print('BtmTiles :-$value');
|
||||||
print('BtmTilesmeta :-$meta');
|
print('BtmTilesmeta :-$meta');
|
||||||
// if (xValues.contains(value))
|
// if (xValues.contains(value))
|
||||||
double closestValue = findClosest(value, xValues);
|
double closestValue = findClosest(value, xValues);
|
||||||
if ((closestValue - value).abs() < 0.15)
|
if ((closestValue - value).abs() < 0.15) {
|
||||||
{
|
|
||||||
|
|
||||||
print("Bottomtiles");
|
print("Bottomtiles");
|
||||||
print(value);
|
print(value);
|
||||||
return Transform.rotate(
|
return Padding(
|
||||||
angle: -0.5, // Slight rotation to improve readability
|
padding: const EdgeInsets.only(top: 1.1),
|
||||||
child: Text(
|
child: Transform.rotate(
|
||||||
value.toInt().toString(),
|
angle: 0.0,
|
||||||
style: TextStyle(color: Colors.black, fontSize: 12),
|
// angle: -0.5, // Slight rotation to improve readability
|
||||||
|
child: Text(
|
||||||
|
value.toInt().toString(),
|
||||||
|
style: TextStyle(color: Colors.black, fontSize: 12),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -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.20+21
|
version: 1.0.23+24
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.2.3 <4.0.0"
|
sdk: ">=3.2.3 <4.0.0"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user