charts added

This commit is contained in:
venbaittech 2025-01-07 09:35:28 +05:30
parent 1bde1c624a
commit 066235889b
7 changed files with 1873 additions and 111 deletions

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="main.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="filePath" value="$PROJECT_DIR$/lib/main.dart" />
<option name="filePath" value="$PROJECT_DIR$/frontend/lib/main.dart" />
<method v="2" />
</configuration>
</component>

View File

@ -295,6 +295,7 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:uae_stat/presentation/Screens/auth_verification/registration.dart';
import 'package:uae_stat/presentation/Screens/demo_home2.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
import '../domain/use_cases/preferences_use_case.dart';
@ -302,6 +303,7 @@ import '../presentation/Screens/auth_verification/changepassword.dart';
import '../presentation/Screens/auth_verification/confirm_password.dart';
import '../presentation/Screens/auth_verification/create_new_pw.dart';
import '../presentation/Screens/auth_verification/otp_verification.dart';
import '../presentation/Screens/charts/chart.dart';
import '../presentation/Screens/demo_home.dart';
import '../presentation/Screens/profilepage.dart';
import '../presentation/routes/auth_routes/login_route.dart';
@ -313,13 +315,12 @@ final GoRouter router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => LoginRoute(),
builder: (context, state) => LoginRoute(),
//builder: (context, state) => MyHomePage(),
),
GoRoute(
path: '/login',
builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/myhomepage',
@ -330,8 +331,20 @@ builder: (context, state) => LoginRoute(),
builder: (context, state) => RegisterScreen(),
),
GoRoute(
path: '/DemoHome',
builder: (context, state) => ChartPage(),
path: '/DemoHome/:dataSets',
builder: (context, state) {
final dataSets = state.pathParameters['dataSets']!;
print('Router $dataSets');
return ChartPage(dataSets: dataSets);
},
),
GoRoute(
path: '/Chart/:dataSets',
builder: (context, state) {
final dataSets = state.pathParameters['dataSets']!;
print('Router $dataSets');
return ChartScreen(dataSets: dataSets);
},
),
GoRoute(
path: '/mailverification',
@ -390,4 +403,3 @@ builder: (context, state) => LoginRoute(),
),
],
);

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,15 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChartPage(),
home: ChartPage(dataSets: ''),
);
}
}
class ChartPage extends StatefulWidget {
final String dataSets;
const ChartPage({Key? key, required this.dataSets});
@override
ChartPageState createState() => ChartPageState();
}
@ -30,13 +33,13 @@ class ChartPageState extends State<ChartPage> {
@override
void initState() {
super.initState();
fetchChartData();
fetchChartData(widget.dataSets);
}
Future<void> fetchChartData() async {
Future<void> fetchChartData(datasets) async {
const baseUrl =
'https://pb.venbait.in/api/custom/apicall'; // Replace with your server URL
final url = Uri.parse('$baseUrl?dataset=hotels');
final url = Uri.parse('$baseUrl?dataset=$datasets');
try {
final response = await http.get(url);
@ -57,24 +60,34 @@ class ChartPageState extends State<ChartPage> {
}
List<ChartData> parseLineChartData(List<dynamic> response) {
return response.map((entry) {
// Attempt to fetch the TIMEPERIOD
final rawTimePeriod =
entry['ObsKey']?['Year'] ?? entry['ObsKey']?['TIME_PERIOD'];
final formattedTimePeriod = rawTimePeriod != null
? rawTimePeriod.toString() // Use as-is if valid
: 'Unknown'; // Fallback value if null
// Group by timePeriod (year) and sum the values
Map<String, double> groupedData = {};
// Parse the value or fallback to 0.0
response.forEach((entry) {
final year = entry['ObsKey']['TIME_PERIOD']?.toString() ?? 'Unknown';
final value =
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
0.0;
return ChartData(
timePeriod: formattedTimePeriod,
value: value,
);
}).toList();
// Add the value to the existing year (if exists) or initialize it
if (groupedData.containsKey(year)) {
groupedData[year] = groupedData[year]! + value;
} else {
groupedData[year] = value;
}
});
// Sort the grouped data by year in ascending order
var sortedEntries = groupedData.entries.toList()
..sort((a, b) => int.parse(a.key).compareTo(int.parse(b.key)));
// Convert the sorted data to a list of ChartData
return sortedEntries
.map((entry) => ChartData(
timePeriod: entry.key,
value: entry.value,
value1: 0.0)) // Add value1 as 0.0
.toList();
}
List<ChartData> parseBarChartData(List<dynamic> response) {
@ -82,63 +95,127 @@ class ChartPageState extends State<ChartPage> {
.asMap()
.entries
.map((entry) => ChartData(
timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ??
'Unknown', // Fallback to 'Unknown' if null
timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ?? 'Unknown',
value: double.tryParse(
entry.value['ObsValue']['Value'].toString()) ??
0.0, // Handle null/invalid value
0.0,
value1: 0.0, // Ensure value1 is passed as well
))
.toList();
}
List<ChartData> parseColumnChartData(List<dynamic> response) {
List<ChartData> chartDataList = [];
// Temporary map to store values by TIME_PERIOD
Map<String, ChartData> timePeriodMap = {};
for (var entry in response) {
String timePeriod = entry['ObsKey']['TIME_PERIOD'].toString();
double value =
double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
0.0;
String indicator = entry['ObsKey']['H_INDICATOR'];
// If the entry is for TOR, map it to 'value'
if (indicator == 'TOR') {
if (timePeriodMap.containsKey(timePeriod)) {
// Update the value by creating a new ChartData object
timePeriodMap[timePeriod] = ChartData(
timePeriod: timePeriod,
value: value, // Set the new value
value1: timePeriodMap[timePeriod]?.value1 ?? 0.0,
);
} else {
timePeriodMap[timePeriod] = ChartData(
timePeriod: timePeriod,
value: value,
value1: 0.0,
);
}
}
// If the entry is for TAR, map it to 'value1'
if (indicator == 'TAR') {
if (timePeriodMap.containsKey(timePeriod)) {
// Create a new ChartData object with the updated value1
timePeriodMap[timePeriod] = ChartData(
timePeriod: timePeriod,
value: timePeriodMap[timePeriod]?.value ??
0.0, // Retain the current value
value1: value, // Update the value1
);
} else {
timePeriodMap[timePeriod] = ChartData(
timePeriod: timePeriod,
value: 0.0,
value1: value,
);
}
}
}
// Convert the map to a list
chartDataList = timePeriodMap.values.toList();
return chartDataList;
}
Widget buildChart(dynamic chartData) {
print('chartData $chartData');
switch (chartData['chart_type']) {
case 'line':
case 'area':
return SfCartesianChart(
primaryXAxis: CategoryAxis(
title: AxisTitle(text: 'Year'),
labelRotation: 45, // Rotate labels if they overlap
),
title: ChartTitle(text: 'Hotel Estabhlishments'),
legend: Legend(isVisible: true),
tooltipBehavior: TooltipBehavior(
enable: true,
builder: (dynamic data, dynamic point, dynamic series,
int pointIndex, int seriesIndex) {
return Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Text(
'${data.timePeriod}: ${formatNumber(data.value)}',
style: const TextStyle(color: Colors.black),
),
);
},
),
series: <CartesianSeries<ChartData, String>>[
LineSeries<ChartData, String>(
dataSource: parseLineChartData(chartData['response']),
xValueMapper: (ChartData data, _) => data.timePeriod,
yValueMapper: (ChartData data, _) => data.value,
name: chartData['dataset'],
color: Colors.red,
dataLabelSettings: DataLabelSettings(
isVisible: true,
builder: (dynamic data, dynamic point, dynamic series,
int pointIndex, int seriesIndex) {
return Text(
formatNumber(data.value),
style: const TextStyle(fontSize: 12, color: Colors.black),
);
},
),
primaryXAxis: CategoryAxis(
title: AxisTitle(text: 'Year'),
labelRotation: 45, // Rotate labels if they overlap
),
],
);
title: ChartTitle(text: 'Hotel Estabhlishments'),
legend: Legend(isVisible: true),
tooltipBehavior: TooltipBehavior(
enable: true,
builder: (dynamic data, dynamic point, dynamic series,
int pointIndex, int seriesIndex) {
return Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Text(
'${data.timePeriod}: ${formatNumber(data.value)}',
style: const TextStyle(color: Colors.black),
),
);
},
),
series: <CartesianSeries>[
// AreaSeries for the area chart
AreaSeries<ChartData, String>(
dataSource: parseLineChartData(
chartData['response']), // your chart data
color: Color(0xFF7DAFBC), // Area color
borderDrawMode: BorderDrawMode
.excludeBottom, // Optional, adjust border settings
borderColor: Colors.green, // Border color
borderWidth: 2, // Border width
xValueMapper: (ChartData data, _) =>
data.timePeriod, // Map x to DateTime
yValueMapper: (ChartData data, _) => data.value,
// name: chartData['dataset'],
name: 'Hotels',
dataLabelSettings: DataLabelSettings(
isVisible: true,
builder: (dynamic data, dynamic point, dynamic series,
int pointIndex, int seriesIndex) {
return Text(
formatNumber(data.value),
style: const TextStyle(fontSize: 12, color: Colors.black),
);
},
), // Map y to numerical value
)
]);
case 'bar':
return SfCartesianChart(
primaryXAxis: CategoryAxis(),
@ -166,7 +243,7 @@ class ChartPageState extends State<ChartPage> {
xValueMapper: (ChartData data, _) => data.timePeriod,
yValueMapper: (ChartData data, _) => data.value,
name: chartData['dataset'],
color: Colors.red,
color: Color(0xFF7DAFBC),
dataLabelSettings: DataLabelSettings(
isVisible: true,
builder: (dynamic data, dynamic point, dynamic series,
@ -182,6 +259,41 @@ class ChartPageState extends State<ChartPage> {
),
],
);
case 'column':
return SfCartesianChart(
primaryXAxis: CategoryAxis(
title: AxisTitle(text: 'Year'),
labelRotation: 45, // Rotate labels if they overlap
),
primaryYAxis: NumericAxis(
title: AxisTitle(text: 'No of rooms'),
),
legend: Legend(isVisible: true),
title: ChartTitle(text: 'Hotel Occupancy Rate'),
enableSideBySideSeriesPlacement: true,
tooltipBehavior: TooltipBehavior(enable: true),
series: <CartesianSeries<ChartData, int>>[
// First Series (value)
ColumnSeries<ChartData, int>(
name: 'Available Rooms',
// opacity: 0.9,
// width: 0.4,
color: Color(0xFF587BA3),
dataSource: parseColumnChartData(chartData['response']),
xValueMapper: (ChartData data, _) => int.parse(data.timePeriod),
yValueMapper: (ChartData data, _) => data.value1,
),
// Second Series (value1)
ColumnSeries<ChartData, int>(
color: Color(0xFF90B0D5),
name: 'Occupied Rooms',
dataSource: parseColumnChartData(chartData['response']),
xValueMapper: (ChartData data, _) => int.parse(data.timePeriod),
yValueMapper: (ChartData data, _) => data.value,
),
], // Numeric Y-axis to plot the values
);
default:
return Center(child: Text('Unknown chart type'));
}
@ -192,46 +304,84 @@ class ChartPageState extends State<ChartPage> {
return Scaffold(
backgroundColor: const Color(0xFF7DAFBC),
appBar: AppBar(
backgroundColor: Color(0xFF7DAFBC),
backgroundColor: const Color(0xFF7DAFBC),
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () {
context.go('/myhomepage');
},
),
title: Text(
title: const Text(
'Charts',
style: TextStyle(color: Colors.white),
),
),
body: isLoading
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: chartsData.length,
itemBuilder: (context, index) {
return Card(
margin: EdgeInsets.all(10),
? const Center(child: CircularProgressIndicator())
: Column(
children: [
Card(
margin: const EdgeInsets.all(10),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Text(
// 'Chart: ${chartsData[index]['chart_type']}',
// style: TextStyle(
// fontSize: 18, fontWeight: FontWeight.bold),
// ),
// SizedBox(height: 10),
Container(
height: 300,
child: buildChart(chartsData[index]),
children: const [
Text(
'Card 1 Title',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('Content for the first card goes here.'),
],
),
),
);
},
),
Card(
margin: const EdgeInsets.all(10),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Card 2 Title',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('Content for the second card goes here.'),
],
),
),
),
Expanded(
child: ListView.builder(
itemCount: chartsData.length,
itemBuilder: (context, index) {
return Card(
margin: const EdgeInsets.all(10),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 300,
child: buildChart(chartsData[index]),
),
],
),
),
);
},
),
),
],
),
);
}
@ -240,23 +390,35 @@ class ChartPageState extends State<ChartPage> {
class ChartData {
final String timePeriod;
final double value;
final double value1;
final String formattedValue;
ChartData({required this.timePeriod, required this.value})
ChartData(
{required this.timePeriod, required this.value, required this.value1})
: formattedValue = formatNumber(value);
}
// String formatNumber(double value) {
// if (value >= 1e12) {
// return '${(value / 1e12).toStringAsFixed(2)} T'; // Trillions
// } else if (value >= 1e9) {
// return '${(value / 1e9).toStringAsFixed(2)} B'; // Billions
// } else if (value >= 1e6) {
// return '${(value / 1e6).toStringAsFixed(2)} M'; // Millions
// } else if (value >= 1e5) {
// return '${(value / 1e5).toStringAsFixed(2)} L'; // Lakhs
// } else if (value >= 1e3) {
// return '${(value / 1e3).toStringAsFixed(2)} K'; // Thousands
// }
// return value.toStringAsFixed(2); // Default to two decimal places
// }
String formatNumber(double value) {
if (value >= 1e12) {
return '${(value / 1e12).toStringAsFixed(2)} T'; // Trillions
} else if (value >= 1e9) {
if (value >= 1e9) {
return '${(value / 1e9).toStringAsFixed(2)} B'; // Billions
} else if (value >= 1e6) {
return '${(value / 1e6).toStringAsFixed(2)} M'; // Millions
} else if (value >= 1e5) {
return '${(value / 1e5).toStringAsFixed(2)} L'; // Lakhs
} else if (value >= 1e3) {
return '${(value / 1e3).toStringAsFixed(2)} K'; // Thousands
}
return value.toStringAsFixed(2); // Default to two decimal places
return value
.toStringAsFixed(2); // Default to two decimal places for smaller numbers
}

View File

@ -0,0 +1,328 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_charts/charts.dart'; // Import Syncfusion charts package
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChartPage2(dataSets: ''),
);
}
}
class ChartPage2 extends StatefulWidget {
final String dataSets;
const ChartPage2({Key? key, required this.dataSets});
@override
ChartPageState createState() => ChartPageState();
}
class ChartPageState extends State<ChartPage2> {
List<dynamic> chartsData = [];
bool isLoading = true;
@override
void initState() {
super.initState();
fetchChartData(widget.dataSets);
}
Future<void> fetchChartData(dataSets) async {
const baseUrl =
'https://pb.venbait.in/api/custom/apicall'; // Replace with your server URL
final url = Uri.parse('$baseUrl?dataset=$dataSets');
try {
final response = await http.get(url);
if (response.statusCode == 200) {
setState(() {
chartsData = jsonDecode(response.body);
isLoading = false;
});
} else {
throw Exception('Failed to load data');
}
} catch (error) {
setState(() {
isLoading = false;
});
print('Error fetching data: $error');
}
}
List<ChartData> parseLineChartData(List<dynamic> response) {
return response.map((entry) {
// Attempt to fetch the TIMEPERIOD
final rawTimePeriod =
entry['ObsKey']?['Year'] ?? entry['ObsKey']?['TIME_PERIOD'];
final formattedTimePeriod = rawTimePeriod != null
? rawTimePeriod.toString() // Use as-is if valid
: 'Unknown'; // Fallback value if null
// Parse the value or fallback to 0.0
final value =
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
0.0;
return ChartData(
timePeriod: formattedTimePeriod,
value: value,
);
}).toList();
}
List<ChartData> parseBarChartData(List<dynamic> response) {
return response
.asMap()
.entries
.map((entry) => ChartData(
timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ??
'Unknown', // Fallback to 'Unknown' if null
value: double.tryParse(
entry.value['ObsValue']['Value'].toString()) ??
0.0, // Handle null/invalid value
))
.toList();
}
// Update parseColumnChartData for column chart
List<ChartData> parseColumnChartData(List<dynamic> response) {
return response.map((entry) {
// Extract TIME_PERIOD as x
final x =
int.tryParse(entry['ObsKey']?['TIME_PERIOD']?.toString() ?? '0') ?? 0;
// Extract Value as y
final y =
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
0.0;
return ChartData(xInt: x, y: y);
}).toList();
}
// Update parseScatterChartData for scatter chart
List<ChartData> parseScatterChartData(List<dynamic> response) {
return response.map((entry) {
// Parse TIME_PERIOD into DateTime
final timePeriod = entry['ObsKey']?['TIME_PERIOD'];
final x = timePeriod != null
? DateTime.tryParse('$timePeriod-01-01') // Convert year to DateTime
: DateTime.now(); // Fallback to current date if null
// Parse Value into double
final y =
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
0.0;
return ChartData(xDateTime: x, y: y);
}).toList();
}
Widget buildChart(dynamic chartData) {
switch (chartData['chart_type']) {
case 'scatter':
return SfCartesianChart(
primaryXAxis: DateTimeAxis(), // Ensure it's DateTimeAxis
tooltipBehavior: TooltipBehavior(enable: true),
title: ChartTitle(text: 'Divorces'),
series: <CartesianSeries>[
ScatterSeries<ChartData, DateTime>(
dataSource: parseScatterChartData(chartData['response']),
xValueMapper: (ChartData data, _) =>
data.xDateTime ?? DateTime.now(),
yValueMapper: (ChartData data, _) => data.y,
name: chartData['dataset'],
dataLabelSettings: DataLabelSettings(isVisible: true),
),
],
);
case 'column':
return SfCartesianChart(
primaryXAxis: NumericAxis(
title: AxisTitle(text: 'Year'),
interval: 1, // Ensure no fractional intervals
),
title: ChartTitle(text: 'Marriages'),
series: <CartesianSeries<ChartData, int>>[
ColumnSeries<ChartData, int>(
dataSource: parseColumnChartData(chartData['response']),
xValueMapper: (ChartData data, _) => data.xInt ?? 0,
yValueMapper: (ChartData data, _) => data.y,
name: chartData['dataset'],
color: Color(0xFF7DAFBC),
width: 0.8,
spacing: 0.2,
dataLabelSettings:
DataLabelSettings(isVisible: true), // Show data labels
),
],
);
case 'line':
return SfCartesianChart(
primaryXAxis: CategoryAxis(),
title: ChartTitle(text: 'Line Chart'),
legend: Legend(isVisible: true),
tooltipBehavior: TooltipBehavior(enable: true),
series: <CartesianSeries<ChartData, String>>[
LineSeries<ChartData, String>(
dataSource: parseLineChartData(chartData['response']),
xValueMapper: (ChartData data, _) => data.timePeriod ?? '',
yValueMapper: (ChartData data, _) => data.value ?? 0.0,
name: 'Sales',
dataLabelSettings: DataLabelSettings(isVisible: true),
),
],
);
case 'bar':
return SfCartesianChart(
primaryXAxis: CategoryAxis(),
title: ChartTitle(text: 'Bar Chart'),
tooltipBehavior: TooltipBehavior(enable: true),
series: <CartesianSeries<ChartData, String>>[
BarSeries<ChartData, String>(
dataSource: parseBarChartData(chartData['response']),
xValueMapper: (ChartData data, _) => data.timePeriod ?? '',
yValueMapper: (ChartData data, _) => data.value ?? 0.0,
name: 'Gold',
color: Color.fromRGBO(8, 142, 255, 1),
),
],
);
default:
return Center(child: Text('Unknown chart type'));
}
}
@override
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF7DAFBC),
appBar: AppBar(
backgroundColor: Color(0xFF7DAFBC),
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () {
context.go('/myhomepage');
},
),
title: Text(
'Charts',
style: TextStyle(color: Colors.white),
),
),
body: isLoading
? Center(child: CircularProgressIndicator())
: Column(
children: [
// Row for two cards
Row(
children: [
// First Card
Expanded(
flex: 6,
child: Card(
margin: EdgeInsets.all(10),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Card 1',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('Content for Card 1 goes here.'),
],
),
),
),
),
// Second Card
Expanded(
flex: 6,
child: Card(
margin: EdgeInsets.all(10),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Card 2',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('Content for Card 2 goes here.'),
],
),
),
),
),
],
),
// List of charts
Expanded(
child: ListView.builder(
itemCount: chartsData.length,
itemBuilder: (context, index) {
return Card(
margin: EdgeInsets.all(10),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
Container(
height: 300,
child: buildChart(chartsData[index]),
),
],
),
),
);
},
),
),
],
),
);
}
}
class ChartData {
final int? xInt; // For column and other charts, using int for x
final DateTime? xDateTime; // For scatter charts, using DateTime for x
final double y; // For column and other charts
final String? timePeriod; // For line and bar charts
final double? value; // For line and bar charts
final double? y2; // For secondary data (stacked column chart)
final double? y3; // For tertiary data (stacked column chart)
final double? y4; // For quaternary data (stacked column chart)
// Constructor that handles all chart cases
ChartData({
this.xInt,
this.xDateTime,
this.y = 0.0,
this.timePeriod,
this.value,
this.y2,
this.y3,
this.y4,
});
}

View File

@ -171,6 +171,20 @@ class MyHomePage extends StatefulWidget {
State<MyHomePage> createState() => _MyHomePageState();
}
void handleInfoCardClick(BuildContext context, String data) {
// Handle navigation and pass dynamic data
print(data);
final dataSets = data;
print(dataSets);
if (dataSets == 'hotels') {
context.go('/Chart/$dataSets');
} else if (dataSets == 'divorces') {
context.go('/Chart/$dataSets');
} else if (dataSets == 'marriages') {
context.go('/Chart/$dataSets');
}
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
@ -226,6 +240,7 @@ class EconomyStats extends StatelessWidget {
value: '1.62T',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(context, 'Inflation'),
),
InfoCard(
title: 'Inflation Rate',
@ -233,6 +248,7 @@ class EconomyStats extends StatelessWidget {
value: '4.82%',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(context, 'Inflation'),
),
],
),
@ -247,6 +263,8 @@ class EconomyStats extends StatelessWidget {
value: '215.4B',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () =>
handleInfoCardClick(context, 'commodities'),
),
InfoCard(
title: 'Hotel Guests',
@ -254,6 +272,7 @@ class EconomyStats extends StatelessWidget {
value: '25.21M',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(context, 'hotels'),
),
],
),
@ -280,18 +299,22 @@ class EconomyStats extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'Population',
subtitle: '(2022) (AED)',
value: '1.62T',
title: 'Divorces',
subtitle: '(2022)',
value: '0',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'divorces'),
),
InfoCard(
title: 'Labor Force',
title: 'Marriages',
subtitle: '(2022)',
value: '4.82%',
value: '0',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'marriages'),
),
],
),
@ -301,11 +324,13 @@ class EconomyStats extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'Hospitals (Gov )',
title: 'Hospitals (Gov)',
subtitle: '(Jan - Jan 2024) - AED',
value: '215.4B',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'Hospitals'),
),
InfoCard(
title: 'Schools',
@ -313,6 +338,8 @@ class EconomyStats extends StatelessWidget {
value: '25.21M',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'Schools'),
),
],
),
@ -345,6 +372,8 @@ class EconomyStats extends StatelessWidget {
value: '1.62T',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(
context, 'Electricity'),
),
InfoCard(
title: 'Cruid oil',
@ -352,6 +381,8 @@ class EconomyStats extends StatelessWidget {
value: '4.82%',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () =>
handleInfoCardClick(context, 'Cruid'),
),
],
),
@ -367,6 +398,8 @@ class EconomyStats extends StatelessWidget {
value: '215.4B',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () =>
handleInfoCardClick(context, 'Export'),
),
InfoCard(
title: 'Desalinated water',
@ -374,6 +407,8 @@ class EconomyStats extends StatelessWidget {
value: '25.21M',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(
context, 'Desalinated'),
),
],
),
@ -433,6 +468,7 @@ class InfoCard extends StatelessWidget {
final String value;
final Color bordercolor;
final Color? textcolor;
final VoidCallback onTap; // New callback parameter
const InfoCard({
Key? key,
@ -441,6 +477,7 @@ class InfoCard extends StatelessWidget {
required this.value,
required this.bordercolor,
this.textcolor,
required this.onTap, // Initialize in constructor
}) : super(key: key);
@override
@ -450,9 +487,7 @@ class InfoCard extends StatelessWidget {
return Expanded(
child: GestureDetector(
onTap: () {
context.go('/DemoHome');
},
onTap: onTap, // Use callback for handling clicks
child: Container(
height: myheight / 9,
width: mywidth / 4,

View File

@ -20,7 +20,7 @@ dependencies:
injectable: ^2.3.2
riverpod_annotation: ^2.3.3
cupertino_icons: ^1.0.6
fl_chart: ^0.69.0
fl_chart: ^0.69.2
marquee: ^2.2.3
# dynamic_layouts:
# git: