Internet Connectivity UI

This commit is contained in:
VINISTAN 2025-01-21 18:59:51 +05:30
commit 10f0dee047
17 changed files with 2655 additions and 2585 deletions

View File

@ -328,7 +328,7 @@ final GoRouter router = GoRouter(
GoRoute(
path: '/',
//builder: (context, state) => LoginRoute(),
builder: (context, state) => MyHomePage(),
builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/internetcheck',
@ -348,29 +348,39 @@ final GoRouter router = GoRouter(
path: '/register',
builder: (context, state) => RegisterScreen(),
),
GoRoute(
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: '/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: '/chartScreen/:dataSets',
builder: (context, state) {
// Retrieve path parameter
final dataSets = state.pathParameters['dataSets']!;
print('Router $dataSets');
// return ChartScreen(dataSets: dataSets);
return ChartScreen1(dataSets: dataSets);
// Retrieve query parameter
final bgColor = state.uri.queryParameters['bgColor'] ??
'0xFFFFFFFF'; // Default white
print('Router dataSets: $dataSets');
print('Router bgColor: $bgColor');
// Pass both values to the screen
return ChartScreen1(
dataSets: dataSets,
bgColor: bgColor,
);
},
),
GoRoute(
@ -423,19 +433,20 @@ final GoRouter router = GoRouter(
path: '/user-guide',
builder: (context, state) => UserGuide(),
routes: <RouteBase>[
GoRoute(path: '/features',
name: 'features',
builder: (context, state) => UsingFeatures(),
GoRoute(
path: '/features',
name: 'features',
builder: (context, state) => UsingFeatures(),
),
GoRoute(path: '/faq',
name: 'faq',
builder: (context, state) => FAQPage(),
GoRoute(
path: '/faq',
name: 'faq',
builder: (context, state) => FAQPage(),
),
GoRoute(path: '/gettingStarted',
name: 'gettingStarted',
builder: (context, state) => GettingStarted(),
GoRoute(
path: '/gettingStarted',
name: 'gettingStarted',
builder: (context, state) => GettingStarted(),
),
],
),
@ -461,10 +472,7 @@ final GoRouter router = GoRouter(
// path: '/uaenumbers',
// builder: (context, state) => UaeNumbers(),
// ),
GoRoute(
path: '/uaenumbers',
builder: (context,state) => UaeNumbers()
),
GoRoute(path: '/uaenumbers', builder: (context, state) => UaeNumbers()),
GoRoute(
path: '/competitiveness',

View File

@ -1,8 +1,11 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/components/constant/constant.dart';
import 'package:http/http.dart' as http;
class UaeNumbers extends StatelessWidget {
const UaeNumbers({super.key});
@ -20,13 +23,49 @@ class UaeNumbers extends StatelessWidget {
}
}
class uaenumberWidget extends StatelessWidget {
class uaenumberWidget extends StatefulWidget {
const uaenumberWidget({super.key});
@override
_UaenumberWidgetState createState() => _UaenumberWidgetState();
}
class _UaenumberWidgetState extends State<uaenumberWidget> {
@override
List<dynamic> homePageData = [];
bool isLoading = true;
@override
void initState() {
fetchData();
}
Future<void> fetchData() async {
// const baseUrl = 'https://pb.venbait.in/api/getHomePageData';
const baseUrl = 'https://pb.venbait.in/api/getUAENumbersData';
try {
final response = await http.get(Uri.parse(baseUrl));
if (response.statusCode == 200) {
setState(() {
homePageData = json.decode(response.body);
// print("HomeDAta $homePageData");
isLoading = false;
});
} else {
throw Exception('Failed to load data');
}
} catch (e) {
setState(() {
isLoading = false;
});
print('Error fetching data: $e');
}
}
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
@ -49,153 +88,112 @@ class uaenumberWidget extends StatelessWidget {
SizedBox(
height: myheight / 35,
),
CustomExpandableTile(
title: 'ECONOMY',
titleBackgroundColor: economyColor,
children: [
buildCategoryTitle('National Accounts', economyColor),
buildCardRow([
buildCard(context, 'GDP (Constant)', '1.62T', '2022 (AED)',
economyColor, economyColor, mywidth / 2.5),
buildCard(context, 'FDI', '1.45T', '2021 (AED)', economyColor,
economyColor, mywidth / 2.5),
]),
buildCategoryTitle('International Trade', economyColor),
buildCardRow([
buildCard(
context,
'Total Trade',
'669.9B',
'Jan - Mar 2024 (AED)',
economyColor,
economyColor,
mywidth / 2.5),
buildCard(
context,
'Total Import',
'686B',
'Jan - Mar 2024 (AED)',
economyColor,
economyColor,
mywidth / 2.5),
]),
buildCardRow([
buildCard(
context,
'Total Export',
'669.9B',
'Jan - Mar 2024 (AED)',
economyColor,
economyColor,
mywidth / 2.5),
buildCard(
context,
'Total ReExport',
'686B',
'Jan - Mar 2024 (AED)',
economyColor,
economyColor,
mywidth / 2.5),
]),
buildCategoryTitle('Prices', economyColor),
buildCardRow([
buildCard(
context,
'Total Export',
'669.9B',
'Jan - Mar 2024 (AED)',
economyColor,
economyColor,
mywidth / 1.2),
]),
],
),
CustomExpandableTile(
title: 'SOCIAL',
titleBackgroundColor: socialColor,
children: [
buildCategoryTitle('Population', socialColor),
buildCardRow([
InkWell(
onTap: () {},
child: buildCard(context, 'Population', '9.89M', '2024',
socialColor, socialColor, mywidth / 2.5)),
buildCard(context, 'Population Growth', '2.1%', '2023',
socialColor, socialColor, mywidth / 2.5),
]),
buildCategoryTitle('Vital Statistics', socialColor),
buildCardRow([
InkWell(onTap : (){
context.go('/marriages');
},child: buildCard(context,'Marriages', '96%', '2023',socialColor,socialColor,mywidth/2.5)),
InkWell(onTap : (){},child: buildCard(context,'Divorces', '1.2K', '2024',socialColor,socialColor,mywidth/2.5)),
]),
buildCategoryTitle('Education', socialColor),
buildCardRow([
buildCard(context, 'General Education', '96%', '2023',
socialColor, socialColor, mywidth / 2.5),
buildCard(context, 'Higher Education', '1.2K', '2024',
socialColor, socialColor, mywidth / 2.5),
]),
buildCategoryTitle('Health', socialColor),
buildCardRow([
buildCard(context, 'Hospital', '96%', '2023', socialColor,
socialColor, mywidth / 2.5),
buildCard(context, 'Clinic and Centres', '1.2K', '2024',
socialColor, socialColor, mywidth / 2.5),
]),
],
),
CustomExpandableTile(
title: 'ENVIRONMENT',
titleBackgroundColor: environmentColor,
children: [
buildCategoryTitle('Agriculture', environmentColor),
buildCardRow([
buildCard(context, 'Crops - Total Area', '27°C', 'Average 2024',
environmentColor, environmentColor, mywidth / 2.5),
buildCard(context, 'Livestock', '120mm', '2024',
environmentColor, environmentColor, mywidth / 2.5),
]),
buildCategoryTitle('Environment', environmentColor),
buildCardRow([
buildCard(context, 'Climate - Max Temp', '15%', '2024',
environmentColor, environmentColor, mywidth / 2.5),
buildCard(context, 'Climate - Min Temp', '30%', '2023',
environmentColor, environmentColor, mywidth / 2.5),
]),
buildCardRow([
buildCard(context, 'Desalinated Produced Water', '15%', '2024',
environmentColor, environmentColor, mywidth / 2.5),
buildCard(context, 'Area of Natural Reserves', '30%', '2023',
environmentColor, environmentColor, mywidth / 2.5),
]),
buildCategoryTitle('Energy', environmentColor),
buildCardRow([
buildCard(context, 'Electricity Production', '15%', '2024',
environmentColor, environmentColor, mywidth / 2.5),
buildCard(context, 'Renewable Energy Production', '30%', '2023',
environmentColor, environmentColor, mywidth / 2.5),
]),
],
),
...homePageData.map<Widget>((mainTopic) {
String colorPattern = mainTopic['color_pattern'];
print('colorPattern $colorPattern');
Color backgroundColor = Color(int.parse(colorPattern));
print('backgroundColor $backgroundColor');
Color borderColor = backgroundColor;
int index = homePageData.indexOf(mainTopic);
bool isFirstTile = index == 0;
return CustomExpandableTile(
index: index,
isExpanded: isFirstTile,
title: mainTopic['main_topic'],
titleBackgroundColor: backgroundColor,
children: _buildSubTopics(
mainTopic['sub_topics'] ?? [],
mywidth,
borderColor,
colorPattern,
),
);
}),
],
),
);
}
List<Widget> _buildSubTopics(List<dynamic> subTopics, double myWidth,
Color borderColor, String colorPattern) {
print('colorPattern123 $borderColor');
// Sort sub-topics based on `sub_topic_list_order`
subTopics.sort((a, b) => (a['sub_topic_list_order'] ?? 0)
.compareTo(b['sub_topic_list_order'] ?? 0));
return subTopics
.map<Widget>((subTopic) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildCategoryTitle(subTopic['sub_topic'], borderColor),
..._buildDataSetCards(subTopic['tile_data'] ?? [], myWidth,
borderColor, colorPattern),
],
))
.toList();
}
List<Widget> _buildDataSetCards(
List<dynamic> tileData, double myWidth, Color borderColor, colorPattern) {
// Sort datasets based on `data_set_list_order`
tileData.sort((a, b) => (a['data_set_list_order'] ?? 0)
.compareTo(b['data_set_list_order'] ?? 0));
List<Widget> rows = [];
for (int i = 0; i < tileData.length; i += 2) {
// Take 1 or 2 items for the row
final rowItems = tileData.sublist(
i,
i + 2 > tileData.length ? tileData.length : i + 2,
);
rows.add(
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: rowItems.map<Widget>((data) {
// Calculate width: full width for one item, half for two items
final cardWidth = rowItems.length == 1
? myWidth
: (myWidth - 16) / 2; // Subtract spacing for padding
return Expanded(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 5.0), // Add spacing
child: buildCard(
context,
data['data_set_tile_heading'] ?? '',
data['value'] ?? '',
data['value_source'] ?? '',
data['data_set'] ?? '',
borderColor,
borderColor,
colorPattern,
cardWidth, // Pass the calculated width
),
),
);
}).toList(),
),
);
}
return rows;
}
Widget buildCategoryTitle(String title, Color color) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: color,
),
),
);
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Center(
child: Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: color,
),
),
));
}
Widget buildCardRow(List<Widget> cards) {
@ -212,43 +210,58 @@ class uaenumberWidget extends StatelessWidget {
);
}
Widget buildCard(BuildContext context, String title, String value,
String subtitle, Color bordercolor, boldColor, double mywidth) {
// double myheight = MediaQuery.of(context).size.height;
// double mywidth = MediaQuery.of(context).size.width;
return Card(
elevation: 2,
child: Container(
width: mywidth,
decoration: BoxDecoration(
color: Colors.white, // Background color
border: Border.all(
color: bordercolor, // Border color
width: 2, // Border width
Widget buildCard(
BuildContext context,
String title,
String value,
String subtitle,
String data_set,
Color bordercolor,
Color boldColor,
colorPattern,
double mywidth,
) {
return GestureDetector(
onTap: () {
print(colorPattern);
context.go('/chartScreen/$data_set?bgColor=$colorPattern');
// context.go('/chartScreen/$data_set');
},
child: Card(
elevation: 1,
child: Container(
width: mywidth,
decoration: BoxDecoration(
color: Colors.white, // Background color
border: Border.all(
color: bordercolor, // Border color
width: 2, // Border width
),
borderRadius:
BorderRadius.circular(12), // Optional: Rounded corners
),
borderRadius: BorderRadius.circular(12), // Optional: Rounded corners
),
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
textAlign: TextAlign.center,
style: robotoRegular11,
),
SizedBox(height: 8),
Text(subtitle, textAlign: TextAlign.center, style: subtitleStyle),
SizedBox(height: 8),
Text(
value,
style: TextStyle(
fontSize: 26,
color: boldColor,
fontWeight: FontWeight.bold,
padding: const EdgeInsets.all(3.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
textAlign: TextAlign.center,
style: robotoRegular11,
),
),
],
SizedBox(height: 0.2),
Text(subtitle, textAlign: TextAlign.center, style: subtitleStyle),
SizedBox(height: 0.7),
Text(
value,
style: TextStyle(
fontSize: 24,
color: boldColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
);
@ -259,11 +272,15 @@ class CustomExpandableTile extends StatefulWidget {
final String title;
final Color titleBackgroundColor;
final List<Widget> children;
final int index;
final bool isExpanded;
const CustomExpandableTile({
required this.title,
required this.titleBackgroundColor,
required this.children,
required this.index,
required this.isExpanded,
});
@override
@ -271,13 +288,21 @@ class CustomExpandableTile extends StatefulWidget {
}
class _CustomExpandableTileState extends State<CustomExpandableTile> {
bool isExpanded = false;
// bool isExpanded = false;
late bool isExpanded;
@override
void initState() {
super.initState();
isExpanded =
widget.isExpanded; // Initialize isExpanded based on widget's property
}
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
return Card(
elevation: 4,
elevation: 0,
child: Column(
children: [
GestureDetector(
@ -289,8 +314,9 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
child: Container(
decoration: BoxDecoration(
color: widget.titleBackgroundColor,
borderRadius: BorderRadius.all(Radius.circular(12))),
padding: const EdgeInsets.all(12),
borderRadius: BorderRadius.all(Radius.circular(35))),
padding: const EdgeInsets.only(
left: 16, bottom: 10, top: 10, right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -307,6 +333,7 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down,
color: Colors.white,
size: 28.0,
),
],
),
@ -317,14 +344,15 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
width: double.infinity,
height: isExpanded ? myheight * 0.52 : 0,
child: isExpanded
? SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.all(Radius.circular(20))),
padding: const EdgeInsets.all(10),
// color: Colors.white,
// borderRadius: BorderRadius.all(Radius.circular(20))
),
padding: const EdgeInsets.all(1),
child: Column(
children: widget.children,
),

View File

@ -193,11 +193,12 @@ class _RegisterScreenState extends State<RegisterScreen> {
print('adminToken- ${adminToken}');
// Create user in PocketBase
final response = await pb.collection('users').create(body: {
'username': _usernameController.text,
'uname': _usernameController.text,
'email': _emailController.text,
'password': _passwordController.text,
'passwordConfirm': _passwordController.text,
'status': 'Pending',
'role': 'user',
}, headers: {
'Authorization': adminToken
});
@ -346,15 +347,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () => {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginRoute()
//ProfileScreen(userId: userID)
),
),
},
onPressed: () => {context.go('/')},
child: Text(
'Go to Login',
),

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,10 @@ import '../filters/search_filter_helper.dart';
class ChartScreen1 extends StatefulWidget {
final String dataSets;
const ChartScreen1({Key? key, required this.dataSets});
final String bgColor;
const ChartScreen1(
{Key? key, required this.dataSets, required String this.bgColor});
@override
_ChartScreen1State createState() => _ChartScreen1State();
}
@ -24,10 +27,13 @@ class _ChartScreen1State extends State<ChartScreen1> {
List<dynamic> cardData = [];
List<dynamic> originalChartsData = [];
List<dynamic> originalCardData = [];
late Color backgroundColor;
@override
void initState() {
super.initState();
final String bgColor = widget.bgColor;
print(' bgColor $bgColor');
fetchChartData(widget.dataSets);
}
@ -368,11 +374,13 @@ class _ChartScreen1State extends State<ChartScreen1> {
@override
Widget build(BuildContext context) {
final color =
Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16));
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.brown[200]!,
backgroundColor: color,
appBar: AppBar(
backgroundColor: Colors.brown[200]!,
backgroundColor: color,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
@ -451,8 +459,8 @@ class _ChartScreen1State extends State<ChartScreen1> {
crossAxisCount: 2, // 2 cards per row
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 177.5 /
180, // Adjusted to maintain width and fixed height
childAspectRatio: 190.5 /
200, // Adjusted to maintain width and fixed height
),
itemBuilder: (context, index) {
final item = cardData[index];
@ -470,49 +478,56 @@ class _ChartScreen1State extends State<ChartScreen1> {
),
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(12.0),
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.public,
color: Color(0xFF90B0D5), size: 22),
const SizedBox(height: 5),
color: Color(0xFF90B0D5), size: 30),
const SizedBox(height: 3),
Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
Text(
'(${data['lastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 10, color: Colors.grey),
fontSize: 11, color: Colors.grey),
),
Text(
'${data['lastYearValue'] ?? 'NA'}',
apiService
.formatAmount(data['lastYearValue']),
style: const TextStyle(
fontSize: 16,
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF90B0D5),
),
),
const Divider(
color: Colors.grey, thickness: 1),
SizedBox(
height: 5, // Height of the divider
child: Divider(
color: Colors.grey,
thickness: 1, // Divider line thickness
),
),
Text(
'${data['secondLastYearValue'] ?? 'NA'}',
apiService.formatAmount(
data['secondLastYearValue']),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Color(0xFF90B0D5),
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFFD83731),
),
),
Text(
'(${data['secondLastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 10, color: Colors.grey),
fontSize: 11, color: Colors.grey),
),
],
),
@ -531,28 +546,28 @@ class _ChartScreen1State extends State<ChartScreen1> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.analytics,
color: Color(0xFF90B0D5), size: 22),
color: Color(0xFF90B0D5), size: 30),
const SizedBox(height: 5),
Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
Text(
'(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 10, color: Colors.grey),
fontSize: 11, color: Colors.grey),
),
Text(
'${data['roundedAverage'] ?? 'NA'}',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Color(0xFF90B0D5),
fontSize: 26,
fontWeight: FontWeight.w900,
color: Color(0xFF11AF22),
),
),
],

View File

@ -56,45 +56,6 @@ class ApiService {
}
}
/// Fetch chart data and categorize it into chart and non-chart data
// Future<void> fetchChartData(String dataSets) async {
// final url = Uri.parse('$baseUrl?dataset=$dataSets');
//
// List<dynamic> isChartData = [];
// List<dynamic> nonChartData = [];
// List<dynamic> originalChartsData = [];
// List<dynamic> originalCardData = [];
//
// try {
// final response = await http.get(url);
//
// if (response.statusCode == 200) {
// final List<dynamic> data = jsonDecode(response.body);
//
// for (var item in data) {
// if (item['is_chart'] == 'true') {
// isChartData.add(item);
// } else if (item['is_chart'] == 'false') {
// nonChartData.add(item);
// }
// }
//
// print('Chart Data: $isChartData');
// print('Non-Chart Data: $nonChartData');
//
// originalChartsData = List.from(isChartData);
// originalCardData = List.from(nonChartData);
//
// print('chartsData $isChartData');
// print('cardData $nonChartData');
// } else {
// throw Exception('Failed to load data');
// }
// } catch (error) {
// print('Error fetching data: $error');
// }
// }
/// Process non-chart data by extracting and calculating values
Map<String, dynamic> processNonChartData(dynamic item) {
print('Processing non-chart data...');
@ -181,4 +142,22 @@ class ApiService {
);
}).toList();
}
String formatAmount(dynamic value) {
// Handle null or non-numeric values
if (value == null || num.tryParse(value.toString()) == null) {
return 'NA';
}
num amount = num.tryParse(value.toString())!;
// Check if the amount is in millions or thousands
if (amount >= 1000000) {
return '${(amount / 1000000).toStringAsFixed(2)}M';
} else if (amount >= 1000) {
return '${(amount / 1000).toStringAsFixed(2)}K';
} else {
return '$amount';
}
}
}

View File

@ -2,7 +2,7 @@ import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
// import 'package:syncfusion_flutter_charts/charts.dart';
class ChartWidget extends StatelessWidget {
final dynamic chartData;
@ -121,80 +121,80 @@ class ChartWidget extends StatelessWidget {
print('groupByValues $groupByValues');
switch (chartData['chart_type']) {
case 'stacked_bar':
String chartTitle =
capitalizeAndSplit(chartData['chart_heading'] ?? '');
// Define a list of colors
final List<Color> uniqueColors = [
Color(0xFF648CBA),
Color(0xFF90B0D5),
Color(0xFF98BCE5),
Color(0xFFA7B5C5),
Color(0xFFBED3EC),
Color(0xFFD4E3F4),
];
return SfCartesianChart(
primaryXAxis: CategoryAxis(),
title: ChartTitle(text: chartData['chart_heading']),
legend: Legend(
isVisible: true,
position: LegendPosition.bottom,
overflowMode: LegendItemOverflowMode.scroll,
),
tooltipBehavior: TooltipBehavior(
enable: true, // Enable tooltips
format: 'point.x : point.y', // Custom tooltip format
),
series: <StackedBarSeries<ChartData, String>>[
for (int i = 0; i < groupByValues.length; i++)
StackedBarSeries<ChartData, String>(
dataSource: parseStackedBarChartData(
chartData, groupByKey, groupByValues.elementAt(i)),
xValueMapper: (ChartData data, _) => data.x ?? '',
yValueMapper: (ChartData data, _) => data.y,
name: groupByValues.elementAt(i),
color: uniqueColors[i % uniqueColors.length],
enableTooltip: true,
),
],
);
case 'stacked_column':
String chartTitle =
capitalizeAndSplit(chartData['chart_heading'] ?? '');
// Define a list of colors
final List<Color> uniqueColors = [
Color(0xFF648CBA),
Color(0xFF90B0D5),
Color(0xFF98BCE5),
Color(0xFFA7B5C5),
Color(0xFFBED3EC),
Color(0xFFD4E3F4),
];
return SfCartesianChart(
primaryXAxis: CategoryAxis(),
title: ChartTitle(text: chartData['chart_heading']),
legend: Legend(
isVisible: true,
position: LegendPosition.bottom,
overflowMode: LegendItemOverflowMode.scroll,
),
tooltipBehavior: TooltipBehavior(
enable: true, // Enable tooltips
format: 'point.x : point.y', // Custom tooltip format
),
series: <CartesianSeries<ChartData, String>>[
for (int i = 0; i < groupByValues.length; i++)
StackedColumnSeries<ChartData, String>(
dataSource: parseStackedBarChartData(
chartData, groupByKey, groupByValues.elementAt(i)),
xValueMapper: (ChartData data, _) => data.x ?? '',
yValueMapper: (ChartData data, _) => data.y,
name: groupByValues.elementAt(i),
color: uniqueColors[i % uniqueColors.length],
enableTooltip: true,
),
],
);
// case 'stacked_bar':
// String chartTitle =
// capitalizeAndSplit(chartData['chart_heading'] ?? '');
// // Define a list of colors
// final List<Color> uniqueColors = [
// Color(0xFF648CBA),
// Color(0xFF90B0D5),
// Color(0xFF98BCE5),
// Color(0xFFA7B5C5),
// Color(0xFFBED3EC),
// Color(0xFFD4E3F4),
// ];
// return SfCartesianChart(
// primaryXAxis: CategoryAxis(),
// title: ChartTitle(text: chartData['chart_heading']),
// legend: Legend(
// isVisible: true,
// position: LegendPosition.bottom,
// overflowMode: LegendItemOverflowMode.scroll,
// ),
// tooltipBehavior: TooltipBehavior(
// enable: true, // Enable tooltips
// format: 'point.x : point.y', // Custom tooltip format
// ),
// series: <StackedBarSeries<ChartData, String>>[
// for (int i = 0; i < groupByValues.length; i++)
// StackedBarSeries<ChartData, String>(
// dataSource: parseStackedBarChartData(
// chartData, groupByKey, groupByValues.elementAt(i)),
// xValueMapper: (ChartData data, _) => data.x ?? '',
// yValueMapper: (ChartData data, _) => data.y,
// name: groupByValues.elementAt(i),
// color: uniqueColors[i % uniqueColors.length],
// enableTooltip: true,
// ),
// ],
// );
// case 'stacked_column':
// String chartTitle =
// capitalizeAndSplit(chartData['chart_heading'] ?? '');
// // Define a list of colors
// final List<Color> uniqueColors = [
// Color(0xFF648CBA),
// Color(0xFF90B0D5),
// Color(0xFF98BCE5),
// Color(0xFFA7B5C5),
// Color(0xFFBED3EC),
// Color(0xFFD4E3F4),
// ];
// return SfCartesianChart(
// primaryXAxis: CategoryAxis(),
// title: ChartTitle(text: chartData['chart_heading']),
// legend: Legend(
// isVisible: true,
// position: LegendPosition.bottom,
// overflowMode: LegendItemOverflowMode.scroll,
// ),
// tooltipBehavior: TooltipBehavior(
// enable: true, // Enable tooltips
// format: 'point.x : point.y', // Custom tooltip format
// ),
// series: <CartesianSeries<ChartData, String>>[
// for (int i = 0; i < groupByValues.length; i++)
// StackedColumnSeries<ChartData, String>(
// dataSource: parseStackedBarChartData(
// chartData, groupByKey, groupByValues.elementAt(i)),
// xValueMapper: (ChartData data, _) => data.x ?? '',
// yValueMapper: (ChartData data, _) => data.y,
// name: groupByValues.elementAt(i),
// color: uniqueColors[i % uniqueColors.length],
// enableTooltip: true,
// ),
// ],
// );
case 'column_chart': // Case 3 for fl_chart column chart
return BarChart(
BarChartData(
@ -369,42 +369,37 @@ class ChartWidget extends StatelessWidget {
Padding(
padding: const EdgeInsets.all(5.0),
child: Wrap(
spacing: 5,
runSpacing: 5,
children: chunkedGroupByValues.map((chunk) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: chunk.map((group) {
List<String> groupByValuesList = groupByValues.toList();
int index = groupByValuesList.indexOf(group);
Color groupColor = _getColorForGroup(index);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: groupColor,
shape: BoxShape.circle,
),
),
SizedBox(width: 3),
Text(
group,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 11),
),
],
spacing: 10, // Horizontal spacing between items
runSpacing: 5, // Vertical spacing between rows
children: chunkedGroupByValues.expand((chunk) {
return chunk.map((group) {
List<String> groupByValuesList = groupByValues.toList();
int index = groupByValuesList.indexOf(group);
Color groupColor = _getColorForGroup(index);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: groupColor,
shape: BoxShape.circle,
),
),
);
}).toList(),
);
SizedBox(width: 5),
Text(
group,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 11),
),
],
);
}).toList();
}).toList(),
),
),
)
],
);
case 'fl_multi_bar':

View File

@ -1,424 +1,424 @@
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: ChartPage(dataSets: ''),
);
}
}
class ChartPage extends StatefulWidget {
final String dataSets;
const ChartPage({Key? key, required this.dataSets});
@override
ChartPageState createState() => ChartPageState();
}
class ChartPageState extends State<ChartPage> {
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) {
// Group by timePeriod (year) and sum the values
Map<String, double> groupedData = {};
response.forEach((entry) {
final year = entry['ObsKey']['TIME_PERIOD']?.toString() ?? 'Unknown';
final value =
double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
0.0;
// 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) {
return response
.asMap()
.entries
.map((entry) => ChartData(
timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ?? 'Unknown',
value: double.tryParse(
entry.value['ObsValue']['Value'].toString()) ??
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 '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>[
// 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(),
title: ChartTitle(text: 'Hotel Occupancy Rate'),
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>>[
BarSeries<ChartData, String>(
dataSource: parseBarChartData(chartData['response']),
xValueMapper: (ChartData data, _) => data.timePeriod,
yValueMapper: (ChartData data, _) => data.value,
name: chartData['dataset'],
color: Color(0xFF7DAFBC),
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),
);
},
),
// isTrackVisible: true,
// trackColor: Colors.red
),
],
);
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'));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF7DAFBC),
appBar: AppBar(
backgroundColor: const Color(0xFF7DAFBC),
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () {
context.go('/myhomepage');
},
),
title: const Text(
'Charts',
style: TextStyle(color: Colors.white),
),
),
body: isLoading
? 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: 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]),
),
],
),
),
);
},
),
),
],
),
);
}
}
class ChartData {
final String timePeriod;
final double value;
final double value1;
final String formattedValue;
ChartData(
{required this.timePeriod, required this.value, required this.value1})
: formattedValue = formatNumber(value);
}
// 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: ChartPage(dataSets: ''),
// );
// }
// }
//
// class ChartPage extends StatefulWidget {
// final String dataSets;
// const ChartPage({Key? key, required this.dataSets});
//
// @override
// ChartPageState createState() => ChartPageState();
// }
//
// class ChartPageState extends State<ChartPage> {
// 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) {
// // Group by timePeriod (year) and sum the values
// Map<String, double> groupedData = {};
//
// response.forEach((entry) {
// final year = entry['ObsKey']['TIME_PERIOD']?.toString() ?? 'Unknown';
// final value =
// double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
// 0.0;
//
// // 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) {
// return response
// .asMap()
// .entries
// .map((entry) => ChartData(
// timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ?? 'Unknown',
// value: double.tryParse(
// entry.value['ObsValue']['Value'].toString()) ??
// 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 '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>[
// // 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(),
// title: ChartTitle(text: 'Hotel Occupancy Rate'),
// 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>>[
// BarSeries<ChartData, String>(
// dataSource: parseBarChartData(chartData['response']),
// xValueMapper: (ChartData data, _) => data.timePeriod,
// yValueMapper: (ChartData data, _) => data.value,
// name: chartData['dataset'],
// color: Color(0xFF7DAFBC),
// 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),
// );
// },
// ),
// // isTrackVisible: true,
// // trackColor: Colors.red
// ),
// ],
// );
// 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'));
// }
// }
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// backgroundColor: const Color(0xFF7DAFBC),
// appBar: AppBar(
// backgroundColor: const Color(0xFF7DAFBC),
// elevation: 0,
// leading: IconButton(
// icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white),
// onPressed: () {
// context.go('/myhomepage');
// },
// ),
// title: const Text(
// 'Charts',
// style: TextStyle(color: Colors.white),
// ),
// ),
// body: isLoading
// ? 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: 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]),
// ),
// ],
// ),
// ),
// );
// },
// ),
// ),
// ],
// ),
// );
// }
// }
//
// class ChartData {
// final String timePeriod;
// final double value;
// final double value1;
// final String formattedValue;
//
// 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
// }
String formatNumber(double value) {
if (value >= 1e9) {
return '${(value / 1e9).toStringAsFixed(2)} B'; // Billions
} else if (value >= 1e6) {
return '${(value / 1e6).toStringAsFixed(2)} M'; // Millions
}
return value
.toStringAsFixed(2); // Default to two decimal places for smaller numbers
}

View File

@ -1,328 +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,
});
}
// 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

@ -37,6 +37,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
true
]; // One for each TextField
bool _isLoading = false;
String _getControllerText(int index) {
if (index == 0) return _usernameController.text;
if (index == 1) return _emailController.text;
@ -169,6 +171,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
// Function to open the date picker
void _pickImage() async {
setState(() {
_isLoading = true; // Start loading
});
final XFile? pickedFile =
await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
@ -179,6 +184,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
fileExtension == 'png' ||
fileExtension == "heic") {
setState(() {
_isLoading = false;
_profileImage = File(pickedFile.path);
});
} else {
@ -365,28 +371,68 @@ class _ProfileScreenState extends State<ProfileScreen> {
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
CircleAvatar(
radius: 50,
backgroundImage: _profileImage != null
? FileImage(_profileImage!)
: AssetImage("assets/edit_profile/profile.png")
as ImageProvider,
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
onTap: _pickImage, // Call `_pickImage` on tap
child: CircleAvatar(
radius: 15,
backgroundColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 15,
color: Colors.grey,
// CircleAvatar(
// radius: 50,
// backgroundImage: _profileImage != null
// ? FileImage(_profileImage!)
// : AssetImage("assets/edit_profile/profile.png")
// as ImageProvider,
// child: Align(
// alignment: Alignment.bottomRight,
// child: GestureDetector(
// onTap: _pickImage, // Call `_pickImage` on tap
// child: CircleAvatar(
// radius: 15,
// backgroundColor: Colors.white,
// child: Icon(
// Icons.camera_alt,
// size: 15,
// color: Colors.grey,
// ),
// ),
// ),
// ),
// ),
Stack(
alignment: Alignment.center,
children: [
// CircleAvatar with the profile image
CircleAvatar(
radius: 50,
backgroundImage: _profileImage != null
? FileImage(_profileImage!)
: AssetImage("assets/edit_profile/profile.png")
as ImageProvider,
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
onTap: _pickImage, // Call `_pickImage` on tap
child: CircleAvatar(
radius: 15,
backgroundColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 15,
color: Colors.grey,
),
),
),
),
),
),
// Conditional loader that shows when _isLoading is true
if (_isLoading)
Positioned(
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor:
AlwaysStoppedAnimation<Color>(Colors.grey),
),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.start,

View File

@ -160,42 +160,19 @@
// );
// }
// }
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:uae_stat/infrastructure/services/InternetConnectivity_Service/InternetConnectivityService.dart';
import 'package:uae_stat/presentation/Screens/online_offline_verification/internet_check.dart';
import '../../drawer_routes/custom_drawer_routes.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:http/http.dart' as http;
class MyHomePage extends ConsumerWidget {
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final isConnected = ref.watch(connectivityProvider);
//final isConnected = false;
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
print('Connectivity Status: $isConnected');
// Trigger navigation based on connectivity state
WidgetsBinding.instance.addPostFrameCallback((_) {
if (isConnected == false) {
context.go('/internetcheck');
}
});
return BaseScaffold(
mycenterTitle: true,
title: SizedBox(
height: myheight / 5,
width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png'))),
body: EconomyStats(),
);
}
State<MyHomePage> createState() => _MyHomePageState();
}
void handleInfoCardClick(BuildContext context, String data) {
@ -212,6 +189,22 @@ void handleInfoCardClick(BuildContext context, String data) {
}
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold(
mycenterTitle: true,
title: SizedBox(
height: myheight / 5,
width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png'))),
body: EconomyStats(),
);
}
}
class EconomyStats extends StatelessWidget {
const EconomyStats({Key? key}) : super(key: key);

View File

@ -23,6 +23,7 @@ class _EditProfileState extends State<EditProfile> {
final _pb = PocketBase('https://pb.venbait.in');
// final _pb = PocketBase('http://127.0.0.1:8090');
bool _isProfileCompleted = false;
bool _isLoading = false;
// Add focus nodes and hint states
final List<FocusNode> _focusNodes = List.generate(4, (_) => FocusNode());
@ -207,16 +208,30 @@ class _EditProfileState extends State<EditProfile> {
// Function to open the date picker
void _pickImage() async {
// setState(() {
// _isLoading = true; // Show loader
// print("Im Loading");
// });
//
// // Simulate an image loading process or network request
// await Future.delayed(Duration(seconds: 8)); // Example delay
final XFile? pickedFile =
await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_isLoading = true; // Start loading
});
print(pickedFile);
final String fileExtension =
pickedFile.path.split('.').last.toLowerCase();
print('fileExtension $fileExtension');
if (fileExtension == 'jpg' ||
fileExtension == 'jpeg' ||
fileExtension == 'png' ||
fileExtension == "heic") {
setState(() {
_isLoading = false;
_profileImage = File(pickedFile.path);
});
} else {
@ -225,6 +240,10 @@ class _EditProfileState extends State<EditProfile> {
);
}
}
setState(() {
_isLoading = false; // Hide loader
});
}
Future<void> _pickDate() async {
@ -369,6 +388,17 @@ class _EditProfileState extends State<EditProfile> {
});
}
Future<void> _loadImage(String url) async {
try {
// Simulate a network delay of 2 seconds (this mimics loading an image from the internet)
// await Future.delayed(Duration(seconds: 3));
print("Image loaded from URL: $url");
} catch (e) {
print("Error loading image: $e");
throw Exception('Failed to load image');
}
}
@override
Widget build(BuildContext context) {
return BaseScaffold(
@ -385,34 +415,112 @@ class _EditProfileState extends State<EditProfile> {
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
CircleAvatar(
radius: 50,
backgroundImage: _profileImage != null
? FileImage(
_profileImage!) // If a local file is selected
: _avatarUrl.isNotEmpty
? NetworkImage(_avatarUrl) // Load from URL
: AssetImage(
"assets/edit_profile/profile.png")
as ImageProvider,
// CircleAvatar(
// radius: 50,
// backgroundImage: _profileImage != null
// ? FileImage(
// _profileImage!) // If a local file is selected
// : _avatarUrl.isNotEmpty
// ? NetworkImage(_avatarUrl) // Load from URL
// : AssetImage(
// "assets/edit_profile/profile.png")
// as ImageProvider,
//
// //backgroundImage: NetworkImage(_avatarUrl) as ImageProvider,
//
// child:
// Align(
// alignment: Alignment.bottomRight,
// child: GestureDetector(
// onTap: _pickImage, // Call `_pickImage` on tap
// child: CircleAvatar(
// radius: 15,
// backgroundColor: Colors.white,
// child: Icon(
// Icons.camera_alt,
// size: 15,
// color: Colors.grey,
// ),
// ),
// ),
// ),
// ),
//backgroundImage: NetworkImage(_avatarUrl) as ImageProvider,
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
onTap: _pickImage, // Call `_pickImage` on tap
child: CircleAvatar(
radius: 15,
backgroundColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 15,
color: Colors.grey,
Stack(
alignment: Alignment.center,
children: [
CircleAvatar(
radius: 50,
backgroundImage: _profileImage != null
? FileImage(
_profileImage!) // If a local file is selected
: _avatarUrl.isNotEmpty
? NetworkImage(
_avatarUrl) // Load from URL
: AssetImage(
"assets/edit_profile/profile.png")
as ImageProvider,
child: _avatarUrl.isNotEmpty
? FutureBuilder(
future: _loadImage(_avatarUrl),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return Center(
child: Icon(Icons.error),
);
} else {
return Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
onTap:
_pickImage, // Call `_pickImage` on tap
child: CircleAvatar(
radius: 15,
backgroundColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 15,
color: Colors.grey,
),
),
),
);
}
},
)
: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
onTap:
_pickImage, // Call `_pickImage` on tap
child: CircleAvatar(
radius: 15,
backgroundColor: Colors.white,
child: Icon(
Icons.camera_alt,
size: 15,
color: Colors.grey,
),
),
),
),
),
if (_isLoading)
Positioned(
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.grey),
),
),
),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.start,

View File

@ -529,7 +529,7 @@ class _FeedbackFormState extends State<FeedbackForm>
)),
RatingBar.builder(
initialRating: rating,
minRating: 1,
minRating: 0,
direction: Axis.horizontal,
allowHalfRating: true,
itemCount: 5,

View File

@ -55,7 +55,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
return User(
id: record.id, // Correctly passing the ID
userName: record.getStringValue('username'),
userName: record.getStringValue('uname'),
emailId: record.getStringValue('email'),
registrationDate: formattedDate,
status: record.getStringValue('status'),

View File

@ -1,15 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:uae_stat/presentation/components/my_toggle.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart';
class BaseScaffold extends ConsumerWidget {
class BaseScaffold extends StatefulWidget {
final Widget body;
final Widget title;
final bool ? showBackButton;
final bool ? mycenterTitle;
final bool? showBackButton;
final bool? mycenterTitle;
final List<Widget>? actions;
final Color? appbarColor, mytitleColor;
@ -19,86 +17,126 @@ class BaseScaffold extends ConsumerWidget {
required this.title,
this.actions,
this.showBackButton = false,
this.mycenterTitle = false, this.appbarColor, this.mytitleColor
this.mycenterTitle = false,
this.appbarColor,
this.mytitleColor,
}) : super(key: key);
// final Widget body;
//
// const BaseScaffold({required this.body});
@override
Widget build(BuildContext context ,WidgetRef ref) {
final locale = ref.watch(localeProvider);
final localeNotifier = ref.read(localeProvider.notifier);
// Get the current route to highlight the active item
_BaseScaffoldState createState() => _BaseScaffoldState();
}
class _BaseScaffoldState extends State<BaseScaffold> {
final _pb = PocketBase('https://pb.venbait.in');
String _avatarUrl = '';
dynamic userId;
String? userName;
String? userEmail;
String? userAvatar;
String? role;
@override
void initState() {
super.initState();
_checkUserId();
}
// Method to retrieve userId from SharedPreferences
Future<String?> getUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('userId'); // Retrieve the userId
}
// Method to check if userId exists and update state
Future<void> _checkUserId() async {
String? fetchedUserId = await getUserId();
if (fetchedUserId != null && fetchedUserId.isNotEmpty) {
setState(() {
userId = fetchedUserId;
});
//print('NAVUser ID: $userId');
_fetchUserData();
} else {
print('No userId found');
// Handle the case where userId is not available
}
}
Future<void> _fetchUserData() async {
try {
final adminAuth = await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final adminToken = adminAuth.token;
//print('adminToken- ${adminToken}');
final userDetailsResponse = await _pb.collection('users').getOne(
userId!,
headers: {
'Authorization': 'Bearer $adminToken',
},
);
print('NAVuserDetails: $userDetailsResponse');
setState(() {
userName = userDetailsResponse.data['uname'] ?? '';
userEmail = userDetailsResponse.data['email'] ?? '';
userAvatar = userDetailsResponse.data['avatar'] ?? '';
role = userDetailsResponse.data['role'] ?? '';
String recordId = userId;
String collectionId =
userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_';
if (userAvatar!.isNotEmpty && recordId.isNotEmpty) {
_avatarUrl =
'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar';
} else {
_avatarUrl = ''; // Reset to default or empty
}
});
} catch (e) {
print('Error fetching user details: $e');
}
}
@override
Widget build(BuildContext context) {
String currentRoute = GoRouterState.of(context).matchedLocation;
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(title: title, backgroundColor : appbarColor,actions: [
// IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
MyToggle(isOn: locale?.languageCode == 'en',
knobTextWhenOn: 'ع',
knobTextWhenOff: 'EN',
pathColorWhenOn: Colors.grey.shade300,
pathColorWhenOff: Colors.grey.shade300,
onTap: (){
ref.read(localeProvider.notifier).toggleLocale();
},),
],
leading:
// Stack(
// children: [
// // Show the back button if showBackButton is true, otherwise show the drawer menu
// if (showBackButton == true)
// Positioned(
// left: 0,
// child: IconButton(
// color: Colors.white,
// icon: Icon(Icons.arrow_back_ios_new),
// onPressed: () {
// Navigator.of(context).pop();
// },
// ),
// ),
// // Show the drawer icon in all cases
// Positioned(
// right: 0,
// child: IconButton(
// color: (showBackButton == true)? Colors.white : Colors.black,
// icon: Icon(Icons.menu),
// onPressed: () {
// // Open the drawer using the Scaffold context
// Scaffold.of(context).openDrawer();
// },
// ),
// ),
// ],
// ),
Stack(
return Scaffold(
appBar: AppBar(
title: widget.title,
backgroundColor: widget.appbarColor,
actions: widget.actions ??
[
IconButton(
onPressed: () {},
icon: const Icon(Icons.toggle_off_outlined),
),
],
leading: Stack(
children: [
// Show the back button if showBackButton is true
if (showBackButton == true)
if (widget.showBackButton == true)
Positioned(
left: 15,
child: IconButton(
color: Colors.white,
icon: Icon(Icons.arrow_back_ios_new),
icon: const Icon(Icons.arrow_back_ios_new),
onPressed: () {
Navigator.of(context).pop();
},
),
),
// Show the drawer icon in all cases
Positioned(
right: 10,
child: Builder(
builder: (BuildContext context) {
return IconButton(
color: (showBackButton == true) ? Colors.white : Colors.black,
icon: Icon(Icons.menu),
color: (widget.showBackButton == true)
? Colors.white
: Colors.black,
icon: const Icon(Icons.menu),
onPressed: () {
// Open the drawer using the Scaffold context
Scaffold.of(context).openDrawer();
},
);
@ -106,14 +144,12 @@ class BaseScaffold extends ConsumerWidget {
),
),
],
)
),
),
drawer: Drawer(
child: ListView(
children: [
DrawerHeader(
//decoration: BoxDecoration(color: Colors.blue),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@ -131,18 +167,39 @@ class BaseScaffold extends ConsumerWidget {
child: Row(
children: [
SizedBox(
width: mywidth / 8,
child: Image(
image: AssetImage(
'assets/edit_profile/profile.png'))),
width: mywidth / 8,
height: mywidth / 8,
child: ClipOval(
child: _avatarUrl.isNotEmpty
? Image(
image: NetworkImage(_avatarUrl),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
)
: Image(
image: AssetImage(
'assets/edit_profile/profile.png'),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
),
//child: Image(image: AssetImage('assets/edit_profile/profile.png'))
),
SizedBox(
width: mywidth / 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Mohammad'),
Text('Mohammad@fcsc.com')
// Text(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),
],
)
],
@ -152,33 +209,26 @@ class BaseScaffold extends ConsumerWidget {
),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/message.png'))),
title: Text('Feedback'),
leading: Icon(Icons.feedback),
title: const Text('Feedback'),
onTap: () => context.go('/feedback'),
),
if (role == 'admin')
ListTile(
leading: Icon(Icons.manage_accounts),
title: const Text('Manage User'),
onTap: () => context.go('/manageuser'),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/manageuser.png'))),
title: Text(AppLocalizations.of(context)!.manage_user),
onTap: () => context.go('/manageuser'),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/book.png'))),
title: Text('User Guide'),
leading: Icon(Icons.book),
title: const Text('User Guide'),
onTap: () => context.go('/user-guide'),
),
ListTile(
leading: Icon(Icons.logout),
title: const Text('Logout'),
onTap: () => context.go('/'),
),
],
),
),
@ -188,49 +238,33 @@ class BaseScaffold extends ConsumerWidget {
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/bottom_bar/home.png'))),
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/bottom_bar/uae_map.png'))),
icon: Icon(Icons.map),
label: 'UAE Numbers',
),
BottomNavigationBarItem(
icon: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image:
AssetImage('assets/icons/bottom_bar/ranking.png'))),
label: 'Competitiveness'),
icon: Icon(Icons.bar_chart),
label: 'Competitiveness',
),
BottomNavigationBarItem(
icon: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/bottom_bar/globe.png'))),
label: 'Country Profile'),
icon: Icon(Icons.public),
label: 'Country Profile',
),
],
selectedItemColor: Colors.black,
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
),
body: body,
body: widget.body,
);
}
//Map the current route to the selected index
int _getSelectedIndex(String route) {
switch (route) {
case '/':
case '/myhomepage':
return 0;
case '/uaenumbers':
return 1;
@ -243,11 +277,10 @@ class BaseScaffold extends ConsumerWidget {
}
}
//Handle navigation when an item is tapped
void _onItemTapped(BuildContext context, int index) {
switch (index) {
case 0:
context.go('/');
context.go('/myhomepage');
break;
case 1:
context.go('/uaenumbers');

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
sha256: "88399e291da5f7e889359681a8f64b18c5123e03576b01f32a6a276611e511c3"
url: "https://pub.dev"
source: hosted
version: "76.0.0"
version: "78.0.0"
_macros:
dependency: transitive
description: dart
@ -18,18 +18,18 @@ packages:
dependency: transitive
description:
name: analyzer
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
sha256: "62899ef43d0b962b056ed2ebac6b47ec76ffd003d5f7c4e4dc870afe63188e33"
url: "https://pub.dev"
source: hosted
version: "6.11.0"
version: "7.1.0"
analyzer_plugin:
dependency: transitive
description:
name: analyzer_plugin
sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161"
sha256: "1d460d14e3c2ae36dc2b32cef847c4479198cf87704f63c3c3c8150ee50c3916"
url: "https://pub.dev"
source: hosted
version: "0.11.3"
version: "0.12.0"
ansicolor:
dependency: transitive
description:
@ -74,50 +74,50 @@ packages:
dependency: transitive
description:
name: build
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
url: "https://pub.dev"
source: hosted
version: "2.4.1"
version: "2.4.2"
build_config:
dependency: transitive
description:
name: build_config
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
version: "1.1.2"
build_daemon:
dependency: transitive
description:
name: build_daemon
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
version: "4.0.3"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
version: "2.4.3"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573"
url: "https://pub.dev"
source: hosted
version: "2.4.13"
version: "2.4.14"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
url: "https://pub.dev"
source: hosted
version: "7.3.2"
version: "8.0.0"
built_collection:
dependency: transitive
description:
@ -258,42 +258,42 @@ packages:
dependency: "direct dev"
description:
name: custom_lint
sha256: "3486c470bb93313a9417f926c7dd694a2e349220992d7b9d14534dc49c15bba9"
sha256: "6d509673c4dd0baa90e60dc8366bc2acc6690f16a7d44bfae31294d82c5d2a62"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.1"
custom_lint_builder:
dependency: transitive
description:
name: custom_lint_builder
sha256: "42cdc41994eeeddab0d7a722c7093ec52bd0761921eeb2cbdbf33d192a234759"
sha256: "8cc525c7b160eb47bb1ded8b2633c0f8b907930eb986ac577aded87cdd2835fe"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.1"
custom_lint_core:
dependency: transitive
description:
name: custom_lint_core
sha256: "02450c3e45e2a6e8b26c4d16687596ab3c4644dd5792e3313aa9ceba5a49b7f5"
sha256: "6dcee8a017181941c51a110da7e267c1d104dc74bec8862eeb8c85b5c8759a9e"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
version: "0.7.1"
custom_lint_visitor:
dependency: transitive
description:
name: custom_lint_visitor
sha256: bfe9b7a09c4775a587b58d10ebb871d4fe618237639b1e84d5ec62d7dfef25f9
sha256: "14df0760dfa81b7b0c398c876045f4e4a343eb2c9d200c66163671dd3e337c1b"
url: "https://pub.dev"
source: hosted
version: "1.0.0+6.11.0"
version: "1.0.0+7.1.0"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac"
url: "https://pub.dev"
source: hosted
version: "2.3.7"
version: "3.0.1"
dbus:
dependency: transitive
description:
@ -491,10 +491,10 @@ packages:
dependency: "direct main"
description:
name: flutter_secure_storage
sha256: "1913841ac4c7bf57cd2e05b717e1fbff7841b542962feff827b16525a781b3e4"
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
url: "https://pub.dev"
source: hosted
version: "9.2.3"
version: "9.2.4"
flutter_secure_storage_linux:
dependency: transitive
description:
@ -565,10 +565,10 @@ packages:
dependency: "direct dev"
description:
name: freezed
sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e"
sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c"
url: "https://pub.dev"
source: hosted
version: "2.5.7"
version: "2.5.8"
freezed_annotation:
dependency: "direct main"
description:
@ -661,10 +661,10 @@ packages:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
version: "4.1.2"
image:
dependency: transitive
description:
@ -685,10 +685,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
sha256: aa6f1280b670861ac45220cc95adc59bb6ae130259d36f980ccb62220dc5e59f
sha256: b62d34a506e12bb965e824b6db4fbf709ee4589cf5d3e99b45ab2287b008ee0c
url: "https://pub.dev"
source: hosted
version: "0.8.12+19"
version: "0.8.12+20"
image_picker_for_web:
dependency: transitive
description:
@ -749,10 +749,10 @@ packages:
dependency: "direct dev"
description:
name: injectable_generator
sha256: af403d76c7b18b4217335e0075e950cd0579fd7f8d7bd47ee7c85ada31680ba1
sha256: b04673a4c88b3a848c0c77bf58b8309f9b9e064d9fe1df5450c8ee1675eaea1a
url: "https://pub.dev"
source: hosted
version: "2.6.2"
version: "2.7.0"
intl:
dependency: "direct main"
description:
@ -789,10 +789,10 @@ packages:
dependency: "direct dev"
description:
name: json_serializable
sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c
sha256: b0a98230538fe5d0b60a22fb6bf1b6cb03471b53e3324ff6069c591679dd59c9
url: "https://pub.dev"
source: hosted
version: "6.9.0"
version: "6.9.3"
jwt_decoder:
dependency: "direct main"
description:
@ -829,10 +829,10 @@ packages:
dependency: transitive
description:
name: lints
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev"
source: hosted
version: "5.0.0"
version: "5.1.1"
logging:
dependency: transitive
description:
@ -853,10 +853,10 @@ packages:
dependency: "direct main"
description:
name: mailer
sha256: e907087cd00719898c493f720dd326af73b00b406ab4af8e79f15d7c5fc24035
sha256: c6ae65c1d40cfe9c06fa50ff9be6c1cfb18cca60a7bb935e318163bd7f1f0d17
url: "https://pub.dev"
source: hosted
version: "6.3.0"
version: "6.4.1"
marquee:
dependency: "direct main"
description:
@ -1045,10 +1045,10 @@ packages:
dependency: transitive
description:
name: pubspec_parse
sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0"
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
url: "https://pub.dev"
source: hosted
version: "1.4.0"
version: "1.5.0"
recase:
dependency: transitive
description:
@ -1077,10 +1077,10 @@ packages:
dependency: transitive
description:
name: riverpod_analyzer_utils
sha256: c6b8222b2b483cb87ae77ad147d6408f400c64f060df7a225b127f4afef4f8c8
sha256: "837a6dc33f490706c7f4632c516bcd10804ee4d9ccc8046124ca56388715fdf3"
url: "https://pub.dev"
source: hosted
version: "0.5.8"
version: "0.5.9"
riverpod_annotation:
dependency: "direct main"
description:
@ -1093,18 +1093,18 @@ packages:
dependency: "direct dev"
description:
name: riverpod_generator
sha256: "63546d70952015f0981361636bf8f356d9cfd9d7f6f0815e3c07789a41233188"
sha256: "120d3310f687f43e7011bb213b90a436f1bbc300f0e4b251a72c39bccb017a4f"
url: "https://pub.dev"
source: hosted
version: "2.6.3"
version: "2.6.4"
riverpod_lint:
dependency: "direct dev"
description:
name: riverpod_lint
sha256: "83e4caa337a9840469b7b9bd8c2351ce85abad80f570d84146911b32086fbd99"
sha256: b05408412b0f75dec954e032c855bc28349eeed2d2187f94519e1ddfdf8b3693
url: "https://pub.dev"
source: hosted
version: "2.6.3"
version: "2.6.4"
rxdart:
dependency: transitive
description:
@ -1124,10 +1124,10 @@ packages:
dependency: "direct main"
description:
name: share_plus
sha256: "6327c3f233729374d0abaafd61f6846115b2a481b4feddd8534211dc10659400"
sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da
url: "https://pub.dev"
source: hosted
version: "10.1.3"
version: "10.1.4"
share_plus_platform_interface:
dependency: transitive
description:
@ -1148,10 +1148,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_android
sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
sha256: bf808be89fe9dc467475e982c1db6c2faf3d2acf54d526cd5ec37d86c99dbd84
url: "https://pub.dev"
source: hosted
version: "2.4.0"
version: "2.4.1"
shared_preferences_foundation:
dependency: transitive
description:
@ -1196,10 +1196,10 @@ packages:
dependency: transitive
description:
name: shelf
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
version: "1.4.1"
version: "1.4.2"
shelf_web_socket:
dependency: transitive
description:
@ -1224,10 +1224,10 @@ packages:
dependency: transitive
description:
name: source_gen
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
version: "2.0.0"
source_helper:
dependency: transitive
description:
@ -1296,18 +1296,18 @@ packages:
dependency: "direct main"
description:
name: syncfusion_flutter_charts
sha256: b2a9f0fd585ef96c081c37697b46d48d3b0f3fe6bddc5011a3542962814fafa8
sha256: "117823c9e2ffcb7fb9868c73263df88751e3bb1f3d81f617cbaf63112f530e9c"
url: "https://pub.dev"
source: hosted
version: "28.1.33"
version: "28.1.39"
syncfusion_flutter_core:
dependency: transitive
description:
name: syncfusion_flutter_core
sha256: b1071c698b502e7d55f91352a8b82d42f49f4c96e523d43b6fade5d5af710048
sha256: "794870919ca73e29c6cb25392a097cdfe58da4d6f3f3d3eccc529ecf52f78752"
url: "https://pub.dev"
source: hosted
version: "28.1.33"
version: "28.1.39"
term_glyph:
dependency: transitive
description:
@ -1408,18 +1408,18 @@ packages:
dependency: transitive
description:
name: url_launcher_web
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
url: "https://pub.dev"
source: hosted
version: "2.3.3"
version: "2.4.0"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
version: "3.1.4"
uuid:
dependency: transitive
description:
@ -1448,18 +1448,18 @@ packages:
dependency: transitive
description:
name: video_player_android
sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898"
sha256: "7018dbcb395e2bca0b9a898e73989e67c0c4a5db269528e1b036ca38bcca0d0b"
url: "https://pub.dev"
source: hosted
version: "2.7.16"
version: "2.7.17"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
sha256: "33224c19775fd244be2d6e3dbd8e1826ab162877bd61123bf71890772119a2b7"
sha256: "8a4e73a3faf2b13512978a43cf1cdda66feeeb900a0527f1fbfd7b19cf3458d3"
url: "https://pub.dev"
source: hosted
version: "2.6.5"
version: "2.6.7"
video_player_platform_interface:
dependency: transitive
description:
@ -1528,10 +1528,10 @@ packages:
dependency: transitive
description:
name: webview_flutter_android
sha256: "3d535126f7244871542b2f0b0fcf94629c9a14883250461f9abe1a6644c1c379"
sha256: d1ee28f44894cbabb1d94cc42f9980297f689ff844d067ec50ff88d86e27d63f
url: "https://pub.dev"
source: hosted
version: "4.2.0"
version: "4.3.0"
webview_flutter_platform_interface:
dependency: transitive
description:
@ -1581,5 +1581,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.5.2 <4.0.0"
flutter: ">=3.24.0"
dart: ">=3.6.0 <4.0.0"
flutter: ">=3.27.0"

View File

@ -57,9 +57,9 @@ dependencies:
provider: ^6.1.2
mailer: ^6.2.0
image_picker: ^1.1.2
syncfusion_flutter_charts: 28.1.33
material_charts: ^0.0.23
flutter_staggered_grid_view: ^0.7.0
syncfusion_flutter_charts: ^28.1.39
connectivity_plus: ^6.1.2
dependency_overrides: