chart flow , Home and Uae number added
This commit is contained in:
parent
d77725601e
commit
e1bc780f50
@ -327,7 +327,7 @@ final GoRouter router = GoRouter(
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/',
|
path: '/',
|
||||||
//builder: (context, state) => LoginRoute(),
|
//builder: (context, state) => LoginRoute(),
|
||||||
builder: (context, state) => MyHomePage(),
|
builder: (context, state) => LoginRoute(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/login',
|
path: '/login',
|
||||||
@ -342,29 +342,39 @@ final GoRouter router = GoRouter(
|
|||||||
path: '/register',
|
path: '/register',
|
||||||
builder: (context, state) => RegisterScreen(),
|
builder: (context, state) => RegisterScreen(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
// GoRoute(
|
||||||
path: '/DemoHome/:dataSets',
|
// path: '/DemoHome/:dataSets',
|
||||||
builder: (context, state) {
|
// builder: (context, state) {
|
||||||
final dataSets = state.pathParameters['dataSets']!;
|
// final dataSets = state.pathParameters['dataSets']!;
|
||||||
print('Router $dataSets');
|
// print('Router $dataSets');
|
||||||
return ChartPage(dataSets: dataSets);
|
// return ChartPage(dataSets: dataSets);
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
GoRoute(
|
// GoRoute(
|
||||||
path: '/Chart/:dataSets',
|
// path: '/Chart/:dataSets',
|
||||||
builder: (context, state) {
|
// builder: (context, state) {
|
||||||
final dataSets = state.pathParameters['dataSets']!;
|
// final dataSets = state.pathParameters['dataSets']!;
|
||||||
print('Router $dataSets');
|
// print('Router $dataSets');
|
||||||
return ChartScreen(dataSets: dataSets);
|
// return ChartScreen(dataSets: dataSets);
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/chartScreen/:dataSets',
|
path: '/chartScreen/:dataSets',
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
// Retrieve path parameter
|
||||||
final dataSets = state.pathParameters['dataSets']!;
|
final dataSets = state.pathParameters['dataSets']!;
|
||||||
print('Router $dataSets');
|
// Retrieve query parameter
|
||||||
// return ChartScreen(dataSets: dataSets);
|
final bgColor = state.uri.queryParameters['bgColor'] ??
|
||||||
return ChartScreen1(dataSets: dataSets);
|
'0xFFFFFFFF'; // Default white
|
||||||
|
|
||||||
|
print('Router dataSets: $dataSets');
|
||||||
|
print('Router bgColor: $bgColor');
|
||||||
|
|
||||||
|
// Pass both values to the screen
|
||||||
|
return ChartScreen1(
|
||||||
|
dataSets: dataSets,
|
||||||
|
bgColor: bgColor,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
@ -417,19 +427,20 @@ final GoRouter router = GoRouter(
|
|||||||
path: '/user-guide',
|
path: '/user-guide',
|
||||||
builder: (context, state) => UserGuide(),
|
builder: (context, state) => UserGuide(),
|
||||||
routes: <RouteBase>[
|
routes: <RouteBase>[
|
||||||
GoRoute(path: '/features',
|
GoRoute(
|
||||||
name: 'features',
|
path: '/features',
|
||||||
builder: (context, state) => UsingFeatures(),
|
name: 'features',
|
||||||
|
builder: (context, state) => UsingFeatures(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
GoRoute(path: '/faq',
|
path: '/faq',
|
||||||
name: 'faq',
|
name: 'faq',
|
||||||
builder: (context, state) => FAQPage(),
|
builder: (context, state) => FAQPage(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
GoRoute(path: '/gettingStarted',
|
path: '/gettingStarted',
|
||||||
name: 'gettingStarted',
|
name: 'gettingStarted',
|
||||||
builder: (context, state) => GettingStarted(),
|
builder: (context, state) => GettingStarted(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -455,10 +466,7 @@ final GoRouter router = GoRouter(
|
|||||||
// path: '/uaenumbers',
|
// path: '/uaenumbers',
|
||||||
// builder: (context, state) => UaeNumbers(),
|
// builder: (context, state) => UaeNumbers(),
|
||||||
// ),
|
// ),
|
||||||
GoRoute(
|
GoRoute(path: '/uaenumbers', builder: (context, state) => UaeNumbers()),
|
||||||
path: '/uaenumbers',
|
|
||||||
builder: (context,state) => UaeNumbers()
|
|
||||||
),
|
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/competitiveness',
|
path: '/competitiveness',
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.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/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/routes/drawer_routes/custom_drawer_routes.dart';
|
||||||
import 'package:uae_stat/presentation/components/constant/constant.dart';
|
import 'package:uae_stat/presentation/components/constant/constant.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
class UaeNumbers extends StatelessWidget {
|
class UaeNumbers extends StatelessWidget {
|
||||||
const UaeNumbers({super.key});
|
const UaeNumbers({super.key});
|
||||||
@ -20,13 +23,49 @@ class UaeNumbers extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class uaenumberWidget extends StatelessWidget {
|
class uaenumberWidget extends StatefulWidget {
|
||||||
const uaenumberWidget({super.key});
|
const uaenumberWidget({super.key});
|
||||||
|
|
||||||
@override
|
@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) {
|
Widget build(BuildContext context) {
|
||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
double mywidth = MediaQuery.of(context).size.width;
|
double mywidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
@ -49,153 +88,112 @@ class uaenumberWidget extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: myheight / 35,
|
height: myheight / 35,
|
||||||
),
|
),
|
||||||
CustomExpandableTile(
|
...homePageData.map<Widget>((mainTopic) {
|
||||||
title: 'ECONOMY',
|
String colorPattern = mainTopic['color_pattern'];
|
||||||
titleBackgroundColor: economyColor,
|
print('colorPattern $colorPattern');
|
||||||
children: [
|
Color backgroundColor = Color(int.parse(colorPattern));
|
||||||
buildCategoryTitle('National Accounts', economyColor),
|
print('backgroundColor $backgroundColor');
|
||||||
buildCardRow([
|
Color borderColor = backgroundColor;
|
||||||
buildCard(context, 'GDP (Constant)', '1.62T', '2022 (AED)',
|
int index = homePageData.indexOf(mainTopic);
|
||||||
economyColor, economyColor, mywidth / 2.5),
|
bool isFirstTile = index == 0;
|
||||||
buildCard(context, 'FDI', '1.45T', '2021 (AED)', economyColor,
|
|
||||||
economyColor, mywidth / 2.5),
|
return CustomExpandableTile(
|
||||||
]),
|
index: index,
|
||||||
buildCategoryTitle('International Trade', economyColor),
|
isExpanded: isFirstTile,
|
||||||
buildCardRow([
|
title: mainTopic['main_topic'],
|
||||||
buildCard(
|
titleBackgroundColor: backgroundColor,
|
||||||
context,
|
children: _buildSubTopics(
|
||||||
'Total Trade',
|
mainTopic['sub_topics'] ?? [],
|
||||||
'669.9B',
|
mywidth,
|
||||||
'Jan - Mar 2024 (AED)',
|
borderColor,
|
||||||
economyColor,
|
colorPattern,
|
||||||
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),
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
Widget buildCategoryTitle(String title, Color color) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
child: Text(
|
child: Center(
|
||||||
title,
|
child: Text(
|
||||||
style: TextStyle(
|
title,
|
||||||
fontSize: 16,
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontSize: 16,
|
||||||
color: color,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
color: color,
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildCardRow(List<Widget> cards) {
|
Widget buildCardRow(List<Widget> cards) {
|
||||||
@ -212,43 +210,58 @@ class uaenumberWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildCard(BuildContext context, String title, String value,
|
Widget buildCard(
|
||||||
String subtitle, Color bordercolor, boldColor, double mywidth) {
|
BuildContext context,
|
||||||
// double myheight = MediaQuery.of(context).size.height;
|
String title,
|
||||||
// double mywidth = MediaQuery.of(context).size.width;
|
String value,
|
||||||
return Card(
|
String subtitle,
|
||||||
elevation: 2,
|
String data_set,
|
||||||
child: Container(
|
Color bordercolor,
|
||||||
width: mywidth,
|
Color boldColor,
|
||||||
decoration: BoxDecoration(
|
colorPattern,
|
||||||
color: Colors.white, // Background color
|
double mywidth,
|
||||||
border: Border.all(
|
) {
|
||||||
color: bordercolor, // Border color
|
return GestureDetector(
|
||||||
width: 2, // Border width
|
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(3.0),
|
||||||
),
|
child: Column(
|
||||||
padding: const EdgeInsets.all(16.0),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
child: Column(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
Text(
|
||||||
children: [
|
title,
|
||||||
Text(
|
textAlign: TextAlign.center,
|
||||||
title,
|
style: robotoRegular11,
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
),
|
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 String title;
|
||||||
final Color titleBackgroundColor;
|
final Color titleBackgroundColor;
|
||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
|
final int index;
|
||||||
|
final bool isExpanded;
|
||||||
|
|
||||||
const CustomExpandableTile({
|
const CustomExpandableTile({
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.titleBackgroundColor,
|
required this.titleBackgroundColor,
|
||||||
required this.children,
|
required this.children,
|
||||||
|
required this.index,
|
||||||
|
required this.isExpanded,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -271,13 +288,21 @@ class CustomExpandableTile extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
return Card(
|
return Card(
|
||||||
elevation: 4,
|
elevation: 0,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@ -289,8 +314,9 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.titleBackgroundColor,
|
color: widget.titleBackgroundColor,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12))),
|
borderRadius: BorderRadius.all(Radius.circular(35))),
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16, bottom: 10, top: 10, right: 10),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@ -307,6 +333,7 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
|||||||
? Icons.keyboard_arrow_up
|
? Icons.keyboard_arrow_up
|
||||||
: Icons.keyboard_arrow_down,
|
: Icons.keyboard_arrow_down,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
|
size: 28.0,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -317,14 +344,15 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
|||||||
duration: Duration(milliseconds: 300),
|
duration: Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
height: isExpanded ? myheight * 0.52 : 0,
|
||||||
child: isExpanded
|
child: isExpanded
|
||||||
? SingleChildScrollView(
|
? SingleChildScrollView(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
borderRadius:
|
// borderRadius: BorderRadius.all(Radius.circular(20))
|
||||||
BorderRadius.all(Radius.circular(20))),
|
),
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(1),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: widget.children,
|
children: widget.children,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -189,11 +189,12 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
|||||||
print('adminToken- ${adminToken}');
|
print('adminToken- ${adminToken}');
|
||||||
// Create user in PocketBase
|
// Create user in PocketBase
|
||||||
final response = await pb.collection('users').create(body: {
|
final response = await pb.collection('users').create(body: {
|
||||||
'username': _usernameController.text,
|
'uname': _usernameController.text,
|
||||||
'email': _emailController.text,
|
'email': _emailController.text,
|
||||||
'password': _passwordController.text,
|
'password': _passwordController.text,
|
||||||
'passwordConfirm': _passwordController.text,
|
'passwordConfirm': _passwordController.text,
|
||||||
'status': 'Pending',
|
'status': 'Pending',
|
||||||
|
'role': 'user',
|
||||||
}, headers: {
|
}, headers: {
|
||||||
'Authorization': adminToken
|
'Authorization': adminToken
|
||||||
});
|
});
|
||||||
@ -316,15 +317,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => {
|
onPressed: () => {context.go('/')},
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(builder: (context) => LoginRoute()
|
|
||||||
|
|
||||||
//ProfileScreen(userId: userID)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
child: Text(
|
child: Text(
|
||||||
'Go to Login',
|
'Go to Login',
|
||||||
),
|
),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,10 @@ import '../filters/search_filter_helper.dart';
|
|||||||
|
|
||||||
class ChartScreen1 extends StatefulWidget {
|
class ChartScreen1 extends StatefulWidget {
|
||||||
final String dataSets;
|
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
|
@override
|
||||||
_ChartScreen1State createState() => _ChartScreen1State();
|
_ChartScreen1State createState() => _ChartScreen1State();
|
||||||
}
|
}
|
||||||
@ -24,10 +27,13 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
|||||||
List<dynamic> cardData = [];
|
List<dynamic> cardData = [];
|
||||||
List<dynamic> originalChartsData = [];
|
List<dynamic> originalChartsData = [];
|
||||||
List<dynamic> originalCardData = [];
|
List<dynamic> originalCardData = [];
|
||||||
|
late Color backgroundColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
final String bgColor = widget.bgColor;
|
||||||
|
print(' bgColor $bgColor');
|
||||||
fetchChartData(widget.dataSets);
|
fetchChartData(widget.dataSets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,11 +374,13 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final color =
|
||||||
|
Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16));
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: _scaffoldKey,
|
key: _scaffoldKey,
|
||||||
backgroundColor: Colors.brown[200]!,
|
backgroundColor: color,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.brown[200]!,
|
backgroundColor: color,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
|
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
|
crossAxisCount: 2, // 2 cards per row
|
||||||
crossAxisSpacing: 10,
|
crossAxisSpacing: 10,
|
||||||
mainAxisSpacing: 10,
|
mainAxisSpacing: 10,
|
||||||
childAspectRatio: 177.5 /
|
childAspectRatio: 190.5 /
|
||||||
180, // Adjusted to maintain width and fixed height
|
200, // Adjusted to maintain width and fixed height
|
||||||
),
|
),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = cardData[index];
|
final item = cardData[index];
|
||||||
@ -470,49 +478,56 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
|||||||
),
|
),
|
||||||
elevation: 4,
|
elevation: 4,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(12.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.public,
|
const Icon(Icons.public,
|
||||||
color: Color(0xFF90B0D5), size: 22),
|
color: Color(0xFF90B0D5), size: 30),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 3),
|
||||||
Text(
|
Text(
|
||||||
'${chart_heading ?? 'NA'}',
|
'${chart_heading ?? 'NA'}',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w400,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'(${data['lastYear'] ?? 'NA'})',
|
'(${data['lastYear'] ?? 'NA'})',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 10, color: Colors.grey),
|
fontSize: 11, color: Colors.grey),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${data['lastYearValue'] ?? 'NA'}',
|
apiService
|
||||||
|
.formatAmount(data['lastYearValue']),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Color(0xFF90B0D5),
|
color: Color(0xFF90B0D5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(
|
SizedBox(
|
||||||
color: Colors.grey, thickness: 1),
|
height: 5, // Height of the divider
|
||||||
|
child: Divider(
|
||||||
|
color: Colors.grey,
|
||||||
|
thickness: 1, // Divider line thickness
|
||||||
|
),
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
'${data['secondLastYearValue'] ?? 'NA'}',
|
apiService.formatAmount(
|
||||||
|
data['secondLastYearValue']),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF90B0D5),
|
color: Color(0xFFD83731),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'(${data['secondLastYear'] ?? 'NA'})',
|
'(${data['secondLastYear'] ?? 'NA'})',
|
||||||
style: const TextStyle(
|
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,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.analytics,
|
const Icon(Icons.analytics,
|
||||||
color: Color(0xFF90B0D5), size: 22),
|
color: Color(0xFF90B0D5), size: 30),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Text(
|
Text(
|
||||||
'${chart_heading ?? 'NA'}',
|
'${chart_heading ?? 'NA'}',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 11,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w400,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})',
|
'(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 10, color: Colors.grey),
|
fontSize: 11, color: Colors.grey),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${data['roundedAverage'] ?? 'NA'}',
|
'${data['roundedAverage'] ?? 'NA'}',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 26,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w900,
|
||||||
color: Color(0xFF90B0D5),
|
color: Color(0xFF11AF22),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -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
|
/// Process non-chart data by extracting and calculating values
|
||||||
Map<String, dynamic> processNonChartData(dynamic item) {
|
Map<String, dynamic> processNonChartData(dynamic item) {
|
||||||
print('Processing non-chart data...');
|
print('Processing non-chart data...');
|
||||||
@ -181,4 +142,22 @@ class ApiService {
|
|||||||
);
|
);
|
||||||
}).toList();
|
}).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';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import 'dart:math';
|
|||||||
|
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
// import 'package:syncfusion_flutter_charts/charts.dart';
|
||||||
|
|
||||||
class ChartWidget extends StatelessWidget {
|
class ChartWidget extends StatelessWidget {
|
||||||
final dynamic chartData;
|
final dynamic chartData;
|
||||||
@ -121,80 +121,80 @@ class ChartWidget extends StatelessWidget {
|
|||||||
print('groupByValues $groupByValues');
|
print('groupByValues $groupByValues');
|
||||||
|
|
||||||
switch (chartData['chart_type']) {
|
switch (chartData['chart_type']) {
|
||||||
case 'stacked_bar':
|
// case 'stacked_bar':
|
||||||
String chartTitle =
|
// String chartTitle =
|
||||||
capitalizeAndSplit(chartData['chart_heading'] ?? '');
|
// capitalizeAndSplit(chartData['chart_heading'] ?? '');
|
||||||
// Define a list of colors
|
// // Define a list of colors
|
||||||
final List<Color> uniqueColors = [
|
// final List<Color> uniqueColors = [
|
||||||
Color(0xFF648CBA),
|
// Color(0xFF648CBA),
|
||||||
Color(0xFF90B0D5),
|
// Color(0xFF90B0D5),
|
||||||
Color(0xFF98BCE5),
|
// Color(0xFF98BCE5),
|
||||||
Color(0xFFA7B5C5),
|
// Color(0xFFA7B5C5),
|
||||||
Color(0xFFBED3EC),
|
// Color(0xFFBED3EC),
|
||||||
Color(0xFFD4E3F4),
|
// Color(0xFFD4E3F4),
|
||||||
];
|
// ];
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(),
|
// primaryXAxis: CategoryAxis(),
|
||||||
title: ChartTitle(text: chartData['chart_heading']),
|
// title: ChartTitle(text: chartData['chart_heading']),
|
||||||
legend: Legend(
|
// legend: Legend(
|
||||||
isVisible: true,
|
// isVisible: true,
|
||||||
position: LegendPosition.bottom,
|
// position: LegendPosition.bottom,
|
||||||
overflowMode: LegendItemOverflowMode.scroll,
|
// overflowMode: LegendItemOverflowMode.scroll,
|
||||||
),
|
// ),
|
||||||
tooltipBehavior: TooltipBehavior(
|
// tooltipBehavior: TooltipBehavior(
|
||||||
enable: true, // Enable tooltips
|
// enable: true, // Enable tooltips
|
||||||
format: 'point.x : point.y', // Custom tooltip format
|
// format: 'point.x : point.y', // Custom tooltip format
|
||||||
),
|
// ),
|
||||||
series: <StackedBarSeries<ChartData, String>>[
|
// series: <StackedBarSeries<ChartData, String>>[
|
||||||
for (int i = 0; i < groupByValues.length; i++)
|
// for (int i = 0; i < groupByValues.length; i++)
|
||||||
StackedBarSeries<ChartData, String>(
|
// StackedBarSeries<ChartData, String>(
|
||||||
dataSource: parseStackedBarChartData(
|
// dataSource: parseStackedBarChartData(
|
||||||
chartData, groupByKey, groupByValues.elementAt(i)),
|
// chartData, groupByKey, groupByValues.elementAt(i)),
|
||||||
xValueMapper: (ChartData data, _) => data.x ?? '',
|
// xValueMapper: (ChartData data, _) => data.x ?? '',
|
||||||
yValueMapper: (ChartData data, _) => data.y,
|
// yValueMapper: (ChartData data, _) => data.y,
|
||||||
name: groupByValues.elementAt(i),
|
// name: groupByValues.elementAt(i),
|
||||||
color: uniqueColors[i % uniqueColors.length],
|
// color: uniqueColors[i % uniqueColors.length],
|
||||||
enableTooltip: true,
|
// enableTooltip: true,
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
case 'stacked_column':
|
// case 'stacked_column':
|
||||||
String chartTitle =
|
// String chartTitle =
|
||||||
capitalizeAndSplit(chartData['chart_heading'] ?? '');
|
// capitalizeAndSplit(chartData['chart_heading'] ?? '');
|
||||||
// Define a list of colors
|
// // Define a list of colors
|
||||||
final List<Color> uniqueColors = [
|
// final List<Color> uniqueColors = [
|
||||||
Color(0xFF648CBA),
|
// Color(0xFF648CBA),
|
||||||
Color(0xFF90B0D5),
|
// Color(0xFF90B0D5),
|
||||||
Color(0xFF98BCE5),
|
// Color(0xFF98BCE5),
|
||||||
Color(0xFFA7B5C5),
|
// Color(0xFFA7B5C5),
|
||||||
Color(0xFFBED3EC),
|
// Color(0xFFBED3EC),
|
||||||
Color(0xFFD4E3F4),
|
// Color(0xFFD4E3F4),
|
||||||
];
|
// ];
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(),
|
// primaryXAxis: CategoryAxis(),
|
||||||
title: ChartTitle(text: chartData['chart_heading']),
|
// title: ChartTitle(text: chartData['chart_heading']),
|
||||||
legend: Legend(
|
// legend: Legend(
|
||||||
isVisible: true,
|
// isVisible: true,
|
||||||
position: LegendPosition.bottom,
|
// position: LegendPosition.bottom,
|
||||||
overflowMode: LegendItemOverflowMode.scroll,
|
// overflowMode: LegendItemOverflowMode.scroll,
|
||||||
),
|
// ),
|
||||||
tooltipBehavior: TooltipBehavior(
|
// tooltipBehavior: TooltipBehavior(
|
||||||
enable: true, // Enable tooltips
|
// enable: true, // Enable tooltips
|
||||||
format: 'point.x : point.y', // Custom tooltip format
|
// format: 'point.x : point.y', // Custom tooltip format
|
||||||
),
|
// ),
|
||||||
series: <CartesianSeries<ChartData, String>>[
|
// series: <CartesianSeries<ChartData, String>>[
|
||||||
for (int i = 0; i < groupByValues.length; i++)
|
// for (int i = 0; i < groupByValues.length; i++)
|
||||||
StackedColumnSeries<ChartData, String>(
|
// StackedColumnSeries<ChartData, String>(
|
||||||
dataSource: parseStackedBarChartData(
|
// dataSource: parseStackedBarChartData(
|
||||||
chartData, groupByKey, groupByValues.elementAt(i)),
|
// chartData, groupByKey, groupByValues.elementAt(i)),
|
||||||
xValueMapper: (ChartData data, _) => data.x ?? '',
|
// xValueMapper: (ChartData data, _) => data.x ?? '',
|
||||||
yValueMapper: (ChartData data, _) => data.y,
|
// yValueMapper: (ChartData data, _) => data.y,
|
||||||
name: groupByValues.elementAt(i),
|
// name: groupByValues.elementAt(i),
|
||||||
color: uniqueColors[i % uniqueColors.length],
|
// color: uniqueColors[i % uniqueColors.length],
|
||||||
enableTooltip: true,
|
// enableTooltip: true,
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
case 'column_chart': // Case 3 for fl_chart column chart
|
case 'column_chart': // Case 3 for fl_chart column chart
|
||||||
return BarChart(
|
return BarChart(
|
||||||
BarChartData(
|
BarChartData(
|
||||||
@ -369,42 +369,37 @@ class ChartWidget extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 5,
|
spacing: 10, // Horizontal spacing between items
|
||||||
runSpacing: 5,
|
runSpacing: 5, // Vertical spacing between rows
|
||||||
children: chunkedGroupByValues.map((chunk) {
|
children: chunkedGroupByValues.expand((chunk) {
|
||||||
return Row(
|
return chunk.map((group) {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
List<String> groupByValuesList = groupByValues.toList();
|
||||||
children: chunk.map((group) {
|
int index = groupByValuesList.indexOf(group);
|
||||||
List<String> groupByValuesList = groupByValues.toList();
|
Color groupColor = _getColorForGroup(index);
|
||||||
int index = groupByValuesList.indexOf(group);
|
|
||||||
Color groupColor = _getColorForGroup(index);
|
return Row(
|
||||||
return Padding(
|
mainAxisSize: MainAxisSize.min,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
children: [
|
||||||
child: Row(
|
Container(
|
||||||
mainAxisSize: MainAxisSize.min,
|
width: 10,
|
||||||
children: [
|
height: 10,
|
||||||
Container(
|
decoration: BoxDecoration(
|
||||||
width: 10,
|
color: groupColor,
|
||||||
height: 10,
|
shape: BoxShape.circle,
|
||||||
decoration: BoxDecoration(
|
),
|
||||||
color: groupColor,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 3),
|
|
||||||
Text(
|
|
||||||
group,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(fontSize: 11),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
SizedBox(width: 5),
|
||||||
}).toList(),
|
Text(
|
||||||
);
|
group,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(fontSize: 11),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
case 'fl_multi_bar':
|
case 'fl_multi_bar':
|
||||||
|
|||||||
@ -1,424 +1,424 @@
|
|||||||
import 'dart:convert';
|
// import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
// import 'package:go_router/go_router.dart';
|
||||||
import 'package:intl/intl.dart';
|
// import 'package:intl/intl.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart'; // Import Syncfusion charts package
|
// import 'package:syncfusion_flutter_charts/charts.dart'; // Import Syncfusion charts package
|
||||||
import 'package:http/http.dart' as http;
|
// import 'package:http/http.dart' as http;
|
||||||
|
//
|
||||||
void main() {
|
// void main() {
|
||||||
runApp(MyApp());
|
// runApp(MyApp());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class MyApp extends StatelessWidget {
|
// class MyApp extends StatelessWidget {
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
// return MaterialApp(
|
||||||
home: ChartPage(dataSets: ''),
|
// home: ChartPage(dataSets: ''),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class ChartPage extends StatefulWidget {
|
// class ChartPage extends StatefulWidget {
|
||||||
final String dataSets;
|
// final String dataSets;
|
||||||
const ChartPage({Key? key, required this.dataSets});
|
// const ChartPage({Key? key, required this.dataSets});
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
ChartPageState createState() => ChartPageState();
|
// ChartPageState createState() => ChartPageState();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class ChartPageState extends State<ChartPage> {
|
// class ChartPageState extends State<ChartPage> {
|
||||||
List<dynamic> chartsData = [];
|
// List<dynamic> chartsData = [];
|
||||||
bool isLoading = true;
|
// bool isLoading = true;
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
void initState() {
|
// void initState() {
|
||||||
super.initState();
|
// super.initState();
|
||||||
fetchChartData(widget.dataSets);
|
// fetchChartData(widget.dataSets);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Future<void> fetchChartData(datasets) async {
|
// Future<void> fetchChartData(datasets) async {
|
||||||
const baseUrl =
|
// const baseUrl =
|
||||||
'https://pb.venbait.in/api/custom/apicall'; // Replace with your server URL
|
// 'https://pb.venbait.in/api/custom/apicall'; // Replace with your server URL
|
||||||
final url = Uri.parse('$baseUrl?dataset=$datasets');
|
// final url = Uri.parse('$baseUrl?dataset=$datasets');
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
final response = await http.get(url);
|
// final response = await http.get(url);
|
||||||
if (response.statusCode == 200) {
|
// if (response.statusCode == 200) {
|
||||||
setState(() {
|
// setState(() {
|
||||||
chartsData = jsonDecode(response.body);
|
// chartsData = jsonDecode(response.body);
|
||||||
isLoading = false;
|
// isLoading = false;
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
throw Exception('Failed to load data');
|
// throw Exception('Failed to load data');
|
||||||
}
|
// }
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
setState(() {
|
// setState(() {
|
||||||
isLoading = false;
|
// isLoading = false;
|
||||||
});
|
// });
|
||||||
print('Error fetching data: $error');
|
// print('Error fetching data: $error');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
List<ChartData> parseLineChartData(List<dynamic> response) {
|
// List<ChartData> parseLineChartData(List<dynamic> response) {
|
||||||
// Group by timePeriod (year) and sum the values
|
// // Group by timePeriod (year) and sum the values
|
||||||
Map<String, double> groupedData = {};
|
// Map<String, double> groupedData = {};
|
||||||
|
//
|
||||||
response.forEach((entry) {
|
// response.forEach((entry) {
|
||||||
final year = entry['ObsKey']['TIME_PERIOD']?.toString() ?? 'Unknown';
|
// final year = entry['ObsKey']['TIME_PERIOD']?.toString() ?? 'Unknown';
|
||||||
final value =
|
// final value =
|
||||||
double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
|
// double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
|
||||||
0.0;
|
// 0.0;
|
||||||
|
//
|
||||||
// Add the value to the existing year (if exists) or initialize it
|
// // Add the value to the existing year (if exists) or initialize it
|
||||||
if (groupedData.containsKey(year)) {
|
// if (groupedData.containsKey(year)) {
|
||||||
groupedData[year] = groupedData[year]! + value;
|
// groupedData[year] = groupedData[year]! + value;
|
||||||
} else {
|
// } else {
|
||||||
groupedData[year] = value;
|
// groupedData[year] = value;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
// Sort the grouped data by year in ascending order
|
// // Sort the grouped data by year in ascending order
|
||||||
var sortedEntries = groupedData.entries.toList()
|
// var sortedEntries = groupedData.entries.toList()
|
||||||
..sort((a, b) => int.parse(a.key).compareTo(int.parse(b.key)));
|
// ..sort((a, b) => int.parse(a.key).compareTo(int.parse(b.key)));
|
||||||
|
//
|
||||||
// Convert the sorted data to a list of ChartData
|
// // Convert the sorted data to a list of ChartData
|
||||||
return sortedEntries
|
// return sortedEntries
|
||||||
.map((entry) => ChartData(
|
// .map((entry) => ChartData(
|
||||||
timePeriod: entry.key,
|
// timePeriod: entry.key,
|
||||||
value: entry.value,
|
// value: entry.value,
|
||||||
value1: 0.0)) // Add value1 as 0.0
|
// value1: 0.0)) // Add value1 as 0.0
|
||||||
.toList();
|
// .toList();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
List<ChartData> parseBarChartData(List<dynamic> response) {
|
// List<ChartData> parseBarChartData(List<dynamic> response) {
|
||||||
return response
|
// return response
|
||||||
.asMap()
|
// .asMap()
|
||||||
.entries
|
// .entries
|
||||||
.map((entry) => ChartData(
|
// .map((entry) => ChartData(
|
||||||
timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ?? 'Unknown',
|
// timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ?? 'Unknown',
|
||||||
value: double.tryParse(
|
// value: double.tryParse(
|
||||||
entry.value['ObsValue']['Value'].toString()) ??
|
// entry.value['ObsValue']['Value'].toString()) ??
|
||||||
0.0,
|
// 0.0,
|
||||||
value1: 0.0, // Ensure value1 is passed as well
|
// value1: 0.0, // Ensure value1 is passed as well
|
||||||
))
|
// ))
|
||||||
.toList();
|
// .toList();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
List<ChartData> parseColumnChartData(List<dynamic> response) {
|
// List<ChartData> parseColumnChartData(List<dynamic> response) {
|
||||||
List<ChartData> chartDataList = [];
|
// List<ChartData> chartDataList = [];
|
||||||
|
//
|
||||||
// Temporary map to store values by TIME_PERIOD
|
// // Temporary map to store values by TIME_PERIOD
|
||||||
Map<String, ChartData> timePeriodMap = {};
|
// Map<String, ChartData> timePeriodMap = {};
|
||||||
|
//
|
||||||
for (var entry in response) {
|
// for (var entry in response) {
|
||||||
String timePeriod = entry['ObsKey']['TIME_PERIOD'].toString();
|
// String timePeriod = entry['ObsKey']['TIME_PERIOD'].toString();
|
||||||
double value =
|
// double value =
|
||||||
double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
|
// double.tryParse(entry['ObsValue']['Value']?.toString() ?? '0.0') ??
|
||||||
0.0;
|
// 0.0;
|
||||||
String indicator = entry['ObsKey']['H_INDICATOR'];
|
// String indicator = entry['ObsKey']['H_INDICATOR'];
|
||||||
|
//
|
||||||
// If the entry is for TOR, map it to 'value'
|
// // If the entry is for TOR, map it to 'value'
|
||||||
if (indicator == 'TOR') {
|
// if (indicator == 'TOR') {
|
||||||
if (timePeriodMap.containsKey(timePeriod)) {
|
// if (timePeriodMap.containsKey(timePeriod)) {
|
||||||
// Update the value by creating a new ChartData object
|
// // Update the value by creating a new ChartData object
|
||||||
timePeriodMap[timePeriod] = ChartData(
|
// timePeriodMap[timePeriod] = ChartData(
|
||||||
timePeriod: timePeriod,
|
// timePeriod: timePeriod,
|
||||||
value: value, // Set the new value
|
// value: value, // Set the new value
|
||||||
value1: timePeriodMap[timePeriod]?.value1 ?? 0.0,
|
// value1: timePeriodMap[timePeriod]?.value1 ?? 0.0,
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
timePeriodMap[timePeriod] = ChartData(
|
// timePeriodMap[timePeriod] = ChartData(
|
||||||
timePeriod: timePeriod,
|
// timePeriod: timePeriod,
|
||||||
value: value,
|
// value: value,
|
||||||
value1: 0.0,
|
// value1: 0.0,
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// If the entry is for TAR, map it to 'value1'
|
// // If the entry is for TAR, map it to 'value1'
|
||||||
if (indicator == 'TAR') {
|
// if (indicator == 'TAR') {
|
||||||
if (timePeriodMap.containsKey(timePeriod)) {
|
// if (timePeriodMap.containsKey(timePeriod)) {
|
||||||
// Create a new ChartData object with the updated value1
|
// // Create a new ChartData object with the updated value1
|
||||||
timePeriodMap[timePeriod] = ChartData(
|
// timePeriodMap[timePeriod] = ChartData(
|
||||||
timePeriod: timePeriod,
|
// timePeriod: timePeriod,
|
||||||
value: timePeriodMap[timePeriod]?.value ??
|
// value: timePeriodMap[timePeriod]?.value ??
|
||||||
0.0, // Retain the current value
|
// 0.0, // Retain the current value
|
||||||
value1: value, // Update the value1
|
// value1: value, // Update the value1
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
timePeriodMap[timePeriod] = ChartData(
|
// timePeriodMap[timePeriod] = ChartData(
|
||||||
timePeriod: timePeriod,
|
// timePeriod: timePeriod,
|
||||||
value: 0.0,
|
// value: 0.0,
|
||||||
value1: value,
|
// value1: value,
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Convert the map to a list
|
// // Convert the map to a list
|
||||||
chartDataList = timePeriodMap.values.toList();
|
// chartDataList = timePeriodMap.values.toList();
|
||||||
|
//
|
||||||
return chartDataList;
|
// return chartDataList;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Widget buildChart(dynamic chartData) {
|
// Widget buildChart(dynamic chartData) {
|
||||||
print('chartData $chartData');
|
// print('chartData $chartData');
|
||||||
switch (chartData['chart_type']) {
|
// switch (chartData['chart_type']) {
|
||||||
case 'area':
|
// case 'area':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(
|
// primaryXAxis: CategoryAxis(
|
||||||
title: AxisTitle(text: 'Year'),
|
// title: AxisTitle(text: 'Year'),
|
||||||
labelRotation: 45, // Rotate labels if they overlap
|
// labelRotation: 45, // Rotate labels if they overlap
|
||||||
),
|
// ),
|
||||||
title: ChartTitle(text: 'Hotel Estabhlishments'),
|
// title: ChartTitle(text: 'Hotel Estabhlishments'),
|
||||||
legend: Legend(isVisible: true),
|
// legend: Legend(isVisible: true),
|
||||||
tooltipBehavior: TooltipBehavior(
|
// tooltipBehavior: TooltipBehavior(
|
||||||
enable: true,
|
// enable: true,
|
||||||
builder: (dynamic data, dynamic point, dynamic series,
|
// builder: (dynamic data, dynamic point, dynamic series,
|
||||||
int pointIndex, int seriesIndex) {
|
// int pointIndex, int seriesIndex) {
|
||||||
return Container(
|
// return Container(
|
||||||
padding: const EdgeInsets.all(8),
|
// padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(5),
|
// borderRadius: BorderRadius.circular(5),
|
||||||
),
|
// ),
|
||||||
child: Text(
|
// child: Text(
|
||||||
'${data.timePeriod}: ${formatNumber(data.value)}',
|
// '${data.timePeriod}: ${formatNumber(data.value)}',
|
||||||
style: const TextStyle(color: Colors.black),
|
// style: const TextStyle(color: Colors.black),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
series: <CartesianSeries>[
|
// series: <CartesianSeries>[
|
||||||
// AreaSeries for the area chart
|
// // AreaSeries for the area chart
|
||||||
AreaSeries<ChartData, String>(
|
// AreaSeries<ChartData, String>(
|
||||||
dataSource: parseLineChartData(
|
// dataSource: parseLineChartData(
|
||||||
chartData['response']), // your chart data
|
// chartData['response']), // your chart data
|
||||||
color: Color(0xFF7DAFBC), // Area color
|
// color: Color(0xFF7DAFBC), // Area color
|
||||||
borderDrawMode: BorderDrawMode
|
// borderDrawMode: BorderDrawMode
|
||||||
.excludeBottom, // Optional, adjust border settings
|
// .excludeBottom, // Optional, adjust border settings
|
||||||
borderColor: Colors.green, // Border color
|
// borderColor: Colors.green, // Border color
|
||||||
borderWidth: 2, // Border width
|
// borderWidth: 2, // Border width
|
||||||
xValueMapper: (ChartData data, _) =>
|
// xValueMapper: (ChartData data, _) =>
|
||||||
data.timePeriod, // Map x to DateTime
|
// data.timePeriod, // Map x to DateTime
|
||||||
yValueMapper: (ChartData data, _) => data.value,
|
// yValueMapper: (ChartData data, _) => data.value,
|
||||||
// name: chartData['dataset'],
|
// // name: chartData['dataset'],
|
||||||
name: 'Hotels',
|
// name: 'Hotels',
|
||||||
dataLabelSettings: DataLabelSettings(
|
// dataLabelSettings: DataLabelSettings(
|
||||||
isVisible: true,
|
// isVisible: true,
|
||||||
builder: (dynamic data, dynamic point, dynamic series,
|
// builder: (dynamic data, dynamic point, dynamic series,
|
||||||
int pointIndex, int seriesIndex) {
|
// int pointIndex, int seriesIndex) {
|
||||||
return Text(
|
// return Text(
|
||||||
formatNumber(data.value),
|
// formatNumber(data.value),
|
||||||
style: const TextStyle(fontSize: 12, color: Colors.black),
|
// style: const TextStyle(fontSize: 12, color: Colors.black),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
), // Map y to numerical value
|
// ), // Map y to numerical value
|
||||||
)
|
// )
|
||||||
]);
|
// ]);
|
||||||
case 'bar':
|
// case 'bar':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(),
|
// primaryXAxis: CategoryAxis(),
|
||||||
title: ChartTitle(text: 'Hotel Occupancy Rate'),
|
// title: ChartTitle(text: 'Hotel Occupancy Rate'),
|
||||||
tooltipBehavior: TooltipBehavior(
|
// tooltipBehavior: TooltipBehavior(
|
||||||
enable: true,
|
// enable: true,
|
||||||
builder: (dynamic data, dynamic point, dynamic series,
|
// builder: (dynamic data, dynamic point, dynamic series,
|
||||||
int pointIndex, int seriesIndex) {
|
// int pointIndex, int seriesIndex) {
|
||||||
return Container(
|
// return Container(
|
||||||
padding: const EdgeInsets.all(8),
|
// padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(5),
|
// borderRadius: BorderRadius.circular(5),
|
||||||
),
|
// ),
|
||||||
child: Text(
|
// child: Text(
|
||||||
'${data.timePeriod}: ${formatNumber(data.value)}',
|
// '${data.timePeriod}: ${formatNumber(data.value)}',
|
||||||
style: const TextStyle(color: Colors.black),
|
// style: const TextStyle(color: Colors.black),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
series: <CartesianSeries<ChartData, String>>[
|
// series: <CartesianSeries<ChartData, String>>[
|
||||||
BarSeries<ChartData, String>(
|
// BarSeries<ChartData, String>(
|
||||||
dataSource: parseBarChartData(chartData['response']),
|
// dataSource: parseBarChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) => data.timePeriod,
|
// xValueMapper: (ChartData data, _) => data.timePeriod,
|
||||||
yValueMapper: (ChartData data, _) => data.value,
|
// yValueMapper: (ChartData data, _) => data.value,
|
||||||
name: chartData['dataset'],
|
// name: chartData['dataset'],
|
||||||
color: Color(0xFF7DAFBC),
|
// color: Color(0xFF7DAFBC),
|
||||||
dataLabelSettings: DataLabelSettings(
|
// dataLabelSettings: DataLabelSettings(
|
||||||
isVisible: true,
|
// isVisible: true,
|
||||||
builder: (dynamic data, dynamic point, dynamic series,
|
// builder: (dynamic data, dynamic point, dynamic series,
|
||||||
int pointIndex, int seriesIndex) {
|
// int pointIndex, int seriesIndex) {
|
||||||
return Text(
|
// return Text(
|
||||||
formatNumber(data.value),
|
// formatNumber(data.value),
|
||||||
style: const TextStyle(fontSize: 12, color: Colors.black),
|
// style: const TextStyle(fontSize: 12, color: Colors.black),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
// isTrackVisible: true,
|
// // isTrackVisible: true,
|
||||||
// trackColor: Colors.red
|
// // trackColor: Colors.red
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
case 'column':
|
// case 'column':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(
|
// primaryXAxis: CategoryAxis(
|
||||||
title: AxisTitle(text: 'Year'),
|
// title: AxisTitle(text: 'Year'),
|
||||||
labelRotation: 45, // Rotate labels if they overlap
|
// labelRotation: 45, // Rotate labels if they overlap
|
||||||
),
|
// ),
|
||||||
primaryYAxis: NumericAxis(
|
// primaryYAxis: NumericAxis(
|
||||||
title: AxisTitle(text: 'No of rooms'),
|
// title: AxisTitle(text: 'No of rooms'),
|
||||||
),
|
// ),
|
||||||
legend: Legend(isVisible: true),
|
// legend: Legend(isVisible: true),
|
||||||
title: ChartTitle(text: 'Hotel Occupancy Rate'),
|
// title: ChartTitle(text: 'Hotel Occupancy Rate'),
|
||||||
enableSideBySideSeriesPlacement: true,
|
// enableSideBySideSeriesPlacement: true,
|
||||||
tooltipBehavior: TooltipBehavior(enable: true),
|
// tooltipBehavior: TooltipBehavior(enable: true),
|
||||||
series: <CartesianSeries<ChartData, int>>[
|
// series: <CartesianSeries<ChartData, int>>[
|
||||||
// First Series (value)
|
// // First Series (value)
|
||||||
|
//
|
||||||
ColumnSeries<ChartData, int>(
|
// ColumnSeries<ChartData, int>(
|
||||||
name: 'Available Rooms',
|
// name: 'Available Rooms',
|
||||||
// opacity: 0.9,
|
// // opacity: 0.9,
|
||||||
// width: 0.4,
|
// // width: 0.4,
|
||||||
color: Color(0xFF587BA3),
|
// color: Color(0xFF587BA3),
|
||||||
dataSource: parseColumnChartData(chartData['response']),
|
// dataSource: parseColumnChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) => int.parse(data.timePeriod),
|
// xValueMapper: (ChartData data, _) => int.parse(data.timePeriod),
|
||||||
yValueMapper: (ChartData data, _) => data.value1,
|
// yValueMapper: (ChartData data, _) => data.value1,
|
||||||
),
|
// ),
|
||||||
// Second Series (value1)
|
// // Second Series (value1)
|
||||||
ColumnSeries<ChartData, int>(
|
// ColumnSeries<ChartData, int>(
|
||||||
color: Color(0xFF90B0D5),
|
// color: Color(0xFF90B0D5),
|
||||||
name: 'Occupied Rooms',
|
// name: 'Occupied Rooms',
|
||||||
dataSource: parseColumnChartData(chartData['response']),
|
// dataSource: parseColumnChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) => int.parse(data.timePeriod),
|
// xValueMapper: (ChartData data, _) => int.parse(data.timePeriod),
|
||||||
yValueMapper: (ChartData data, _) => data.value,
|
// yValueMapper: (ChartData data, _) => data.value,
|
||||||
),
|
// ),
|
||||||
], // Numeric Y-axis to plot the values
|
// ], // Numeric Y-axis to plot the values
|
||||||
);
|
// );
|
||||||
default:
|
// default:
|
||||||
return Center(child: Text('Unknown chart type'));
|
// return Center(child: Text('Unknown chart type'));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
// return Scaffold(
|
||||||
backgroundColor: const Color(0xFF7DAFBC),
|
// backgroundColor: const Color(0xFF7DAFBC),
|
||||||
appBar: AppBar(
|
// appBar: AppBar(
|
||||||
backgroundColor: const Color(0xFF7DAFBC),
|
// backgroundColor: const Color(0xFF7DAFBC),
|
||||||
elevation: 0,
|
// elevation: 0,
|
||||||
leading: IconButton(
|
// leading: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white),
|
// icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
context.go('/myhomepage');
|
// context.go('/myhomepage');
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
title: const Text(
|
// title: const Text(
|
||||||
'Charts',
|
// 'Charts',
|
||||||
style: TextStyle(color: Colors.white),
|
// style: TextStyle(color: Colors.white),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
body: isLoading
|
// body: isLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
// ? const Center(child: CircularProgressIndicator())
|
||||||
: Column(
|
// : Column(
|
||||||
children: [
|
// children: [
|
||||||
Card(
|
// Card(
|
||||||
margin: const EdgeInsets.all(10),
|
// margin: const EdgeInsets.all(10),
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
// padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: const [
|
// children: const [
|
||||||
Text(
|
// Text(
|
||||||
'Card 1 Title',
|
// 'Card 1 Title',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.bold),
|
// fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
// ),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Text('Content for the first card goes here.'),
|
// Text('Content for the first card goes here.'),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Card(
|
// Card(
|
||||||
margin: const EdgeInsets.all(10),
|
// margin: const EdgeInsets.all(10),
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
// padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: const [
|
// children: const [
|
||||||
Text(
|
// Text(
|
||||||
'Card 2 Title',
|
// 'Card 2 Title',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.bold),
|
// fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
// ),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Text('Content for the second card goes here.'),
|
// Text('Content for the second card goes here.'),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: ListView.builder(
|
// child: ListView.builder(
|
||||||
itemCount: chartsData.length,
|
// itemCount: chartsData.length,
|
||||||
itemBuilder: (context, index) {
|
// itemBuilder: (context, index) {
|
||||||
return Card(
|
// return Card(
|
||||||
margin: const EdgeInsets.all(10),
|
// margin: const EdgeInsets.all(10),
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
// padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
Container(
|
// Container(
|
||||||
height: 300,
|
// height: 300,
|
||||||
child: buildChart(chartsData[index]),
|
// child: buildChart(chartsData[index]),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class ChartData {
|
// class ChartData {
|
||||||
final String timePeriod;
|
// final String timePeriod;
|
||||||
final double value;
|
// final double value;
|
||||||
final double value1;
|
// final double value1;
|
||||||
final String formattedValue;
|
// final String formattedValue;
|
||||||
|
//
|
||||||
ChartData(
|
// ChartData(
|
||||||
{required this.timePeriod, required this.value, required this.value1})
|
// {required this.timePeriod, required this.value, required this.value1})
|
||||||
: formattedValue = formatNumber(value);
|
// : 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) {
|
// String formatNumber(double value) {
|
||||||
// if (value >= 1e12) {
|
// if (value >= 1e9) {
|
||||||
// return '${(value / 1e12).toStringAsFixed(2)} T'; // Trillions
|
|
||||||
// } else if (value >= 1e9) {
|
|
||||||
// return '${(value / 1e9).toStringAsFixed(2)} B'; // Billions
|
// return '${(value / 1e9).toStringAsFixed(2)} B'; // Billions
|
||||||
// } else if (value >= 1e6) {
|
// } else if (value >= 1e6) {
|
||||||
// return '${(value / 1e6).toStringAsFixed(2)} M'; // Millions
|
// 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
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,328 +1,328 @@
|
|||||||
import 'dart:convert';
|
// import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
// import 'package:go_router/go_router.dart';
|
||||||
import 'package:intl/intl.dart';
|
// import 'package:intl/intl.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart'; // Import Syncfusion charts package
|
// import 'package:syncfusion_flutter_charts/charts.dart'; // Import Syncfusion charts package
|
||||||
import 'package:http/http.dart' as http;
|
// import 'package:http/http.dart' as http;
|
||||||
|
//
|
||||||
void main() {
|
// void main() {
|
||||||
runApp(MyApp());
|
// runApp(MyApp());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class MyApp extends StatelessWidget {
|
// class MyApp extends StatelessWidget {
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
// return MaterialApp(
|
||||||
home: ChartPage2(dataSets: ''),
|
// home: ChartPage2(dataSets: ''),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class ChartPage2 extends StatefulWidget {
|
// class ChartPage2 extends StatefulWidget {
|
||||||
final String dataSets;
|
// final String dataSets;
|
||||||
const ChartPage2({Key? key, required this.dataSets});
|
// const ChartPage2({Key? key, required this.dataSets});
|
||||||
@override
|
// @override
|
||||||
ChartPageState createState() => ChartPageState();
|
// ChartPageState createState() => ChartPageState();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class ChartPageState extends State<ChartPage2> {
|
// class ChartPageState extends State<ChartPage2> {
|
||||||
List<dynamic> chartsData = [];
|
// List<dynamic> chartsData = [];
|
||||||
bool isLoading = true;
|
// bool isLoading = true;
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
void initState() {
|
// void initState() {
|
||||||
super.initState();
|
// super.initState();
|
||||||
fetchChartData(widget.dataSets);
|
// fetchChartData(widget.dataSets);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Future<void> fetchChartData(dataSets) async {
|
// Future<void> fetchChartData(dataSets) async {
|
||||||
const baseUrl =
|
// const baseUrl =
|
||||||
'https://pb.venbait.in/api/custom/apicall'; // Replace with your server URL
|
// 'https://pb.venbait.in/api/custom/apicall'; // Replace with your server URL
|
||||||
final url = Uri.parse('$baseUrl?dataset=$dataSets');
|
// final url = Uri.parse('$baseUrl?dataset=$dataSets');
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
final response = await http.get(url);
|
// final response = await http.get(url);
|
||||||
if (response.statusCode == 200) {
|
// if (response.statusCode == 200) {
|
||||||
setState(() {
|
// setState(() {
|
||||||
chartsData = jsonDecode(response.body);
|
// chartsData = jsonDecode(response.body);
|
||||||
isLoading = false;
|
// isLoading = false;
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
throw Exception('Failed to load data');
|
// throw Exception('Failed to load data');
|
||||||
}
|
// }
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
setState(() {
|
// setState(() {
|
||||||
isLoading = false;
|
// isLoading = false;
|
||||||
});
|
// });
|
||||||
print('Error fetching data: $error');
|
// print('Error fetching data: $error');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
List<ChartData> parseLineChartData(List<dynamic> response) {
|
// List<ChartData> parseLineChartData(List<dynamic> response) {
|
||||||
return response.map((entry) {
|
// return response.map((entry) {
|
||||||
// Attempt to fetch the TIMEPERIOD
|
// // Attempt to fetch the TIMEPERIOD
|
||||||
final rawTimePeriod =
|
// final rawTimePeriod =
|
||||||
entry['ObsKey']?['Year'] ?? entry['ObsKey']?['TIME_PERIOD'];
|
// entry['ObsKey']?['Year'] ?? entry['ObsKey']?['TIME_PERIOD'];
|
||||||
final formattedTimePeriod = rawTimePeriod != null
|
// final formattedTimePeriod = rawTimePeriod != null
|
||||||
? rawTimePeriod.toString() // Use as-is if valid
|
// ? rawTimePeriod.toString() // Use as-is if valid
|
||||||
: 'Unknown'; // Fallback value if null
|
// : 'Unknown'; // Fallback value if null
|
||||||
|
//
|
||||||
// Parse the value or fallback to 0.0
|
// // Parse the value or fallback to 0.0
|
||||||
final value =
|
// final value =
|
||||||
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
|
// double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
|
||||||
0.0;
|
// 0.0;
|
||||||
|
//
|
||||||
return ChartData(
|
// return ChartData(
|
||||||
timePeriod: formattedTimePeriod,
|
// timePeriod: formattedTimePeriod,
|
||||||
value: value,
|
// value: value,
|
||||||
);
|
// );
|
||||||
}).toList();
|
// }).toList();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
List<ChartData> parseBarChartData(List<dynamic> response) {
|
// List<ChartData> parseBarChartData(List<dynamic> response) {
|
||||||
return response
|
// return response
|
||||||
.asMap()
|
// .asMap()
|
||||||
.entries
|
// .entries
|
||||||
.map((entry) => ChartData(
|
// .map((entry) => ChartData(
|
||||||
timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ??
|
// timePeriod: entry.value['ObsKey']['TIME_PERIOD'] ??
|
||||||
'Unknown', // Fallback to 'Unknown' if null
|
// 'Unknown', // Fallback to 'Unknown' if null
|
||||||
value: double.tryParse(
|
// value: double.tryParse(
|
||||||
entry.value['ObsValue']['Value'].toString()) ??
|
// entry.value['ObsValue']['Value'].toString()) ??
|
||||||
0.0, // Handle null/invalid value
|
// 0.0, // Handle null/invalid value
|
||||||
))
|
// ))
|
||||||
.toList();
|
// .toList();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Update parseColumnChartData for column chart
|
// // Update parseColumnChartData for column chart
|
||||||
List<ChartData> parseColumnChartData(List<dynamic> response) {
|
// List<ChartData> parseColumnChartData(List<dynamic> response) {
|
||||||
return response.map((entry) {
|
// return response.map((entry) {
|
||||||
// Extract TIME_PERIOD as x
|
// // Extract TIME_PERIOD as x
|
||||||
final x =
|
// final x =
|
||||||
int.tryParse(entry['ObsKey']?['TIME_PERIOD']?.toString() ?? '0') ?? 0;
|
// int.tryParse(entry['ObsKey']?['TIME_PERIOD']?.toString() ?? '0') ?? 0;
|
||||||
// Extract Value as y
|
// // Extract Value as y
|
||||||
final y =
|
// final y =
|
||||||
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
|
// double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
|
||||||
0.0;
|
// 0.0;
|
||||||
return ChartData(xInt: x, y: y);
|
// return ChartData(xInt: x, y: y);
|
||||||
}).toList();
|
// }).toList();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Update parseScatterChartData for scatter chart
|
// // Update parseScatterChartData for scatter chart
|
||||||
List<ChartData> parseScatterChartData(List<dynamic> response) {
|
// List<ChartData> parseScatterChartData(List<dynamic> response) {
|
||||||
return response.map((entry) {
|
// return response.map((entry) {
|
||||||
// Parse TIME_PERIOD into DateTime
|
// // Parse TIME_PERIOD into DateTime
|
||||||
final timePeriod = entry['ObsKey']?['TIME_PERIOD'];
|
// final timePeriod = entry['ObsKey']?['TIME_PERIOD'];
|
||||||
final x = timePeriod != null
|
// final x = timePeriod != null
|
||||||
? DateTime.tryParse('$timePeriod-01-01') // Convert year to DateTime
|
// ? DateTime.tryParse('$timePeriod-01-01') // Convert year to DateTime
|
||||||
: DateTime.now(); // Fallback to current date if null
|
// : DateTime.now(); // Fallback to current date if null
|
||||||
|
//
|
||||||
// Parse Value into double
|
// // Parse Value into double
|
||||||
final y =
|
// final y =
|
||||||
double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
|
// double.tryParse(entry['ObsValue']?['Value']?.toString() ?? '0.0') ??
|
||||||
0.0;
|
// 0.0;
|
||||||
|
//
|
||||||
return ChartData(xDateTime: x, y: y);
|
// return ChartData(xDateTime: x, y: y);
|
||||||
}).toList();
|
// }).toList();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Widget buildChart(dynamic chartData) {
|
// Widget buildChart(dynamic chartData) {
|
||||||
switch (chartData['chart_type']) {
|
// switch (chartData['chart_type']) {
|
||||||
case 'scatter':
|
// case 'scatter':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: DateTimeAxis(), // Ensure it's DateTimeAxis
|
// primaryXAxis: DateTimeAxis(), // Ensure it's DateTimeAxis
|
||||||
tooltipBehavior: TooltipBehavior(enable: true),
|
// tooltipBehavior: TooltipBehavior(enable: true),
|
||||||
title: ChartTitle(text: 'Divorces'),
|
// title: ChartTitle(text: 'Divorces'),
|
||||||
series: <CartesianSeries>[
|
// series: <CartesianSeries>[
|
||||||
ScatterSeries<ChartData, DateTime>(
|
// ScatterSeries<ChartData, DateTime>(
|
||||||
dataSource: parseScatterChartData(chartData['response']),
|
// dataSource: parseScatterChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) =>
|
// xValueMapper: (ChartData data, _) =>
|
||||||
data.xDateTime ?? DateTime.now(),
|
// data.xDateTime ?? DateTime.now(),
|
||||||
yValueMapper: (ChartData data, _) => data.y,
|
// yValueMapper: (ChartData data, _) => data.y,
|
||||||
name: chartData['dataset'],
|
// name: chartData['dataset'],
|
||||||
dataLabelSettings: DataLabelSettings(isVisible: true),
|
// dataLabelSettings: DataLabelSettings(isVisible: true),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
case 'column':
|
// case 'column':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: NumericAxis(
|
// primaryXAxis: NumericAxis(
|
||||||
title: AxisTitle(text: 'Year'),
|
// title: AxisTitle(text: 'Year'),
|
||||||
interval: 1, // Ensure no fractional intervals
|
// interval: 1, // Ensure no fractional intervals
|
||||||
),
|
// ),
|
||||||
title: ChartTitle(text: 'Marriages'),
|
// title: ChartTitle(text: 'Marriages'),
|
||||||
series: <CartesianSeries<ChartData, int>>[
|
// series: <CartesianSeries<ChartData, int>>[
|
||||||
ColumnSeries<ChartData, int>(
|
// ColumnSeries<ChartData, int>(
|
||||||
dataSource: parseColumnChartData(chartData['response']),
|
// dataSource: parseColumnChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) => data.xInt ?? 0,
|
// xValueMapper: (ChartData data, _) => data.xInt ?? 0,
|
||||||
yValueMapper: (ChartData data, _) => data.y,
|
// yValueMapper: (ChartData data, _) => data.y,
|
||||||
name: chartData['dataset'],
|
// name: chartData['dataset'],
|
||||||
color: Color(0xFF7DAFBC),
|
// color: Color(0xFF7DAFBC),
|
||||||
width: 0.8,
|
// width: 0.8,
|
||||||
spacing: 0.2,
|
// spacing: 0.2,
|
||||||
dataLabelSettings:
|
// dataLabelSettings:
|
||||||
DataLabelSettings(isVisible: true), // Show data labels
|
// DataLabelSettings(isVisible: true), // Show data labels
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
case 'line':
|
// case 'line':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(),
|
// primaryXAxis: CategoryAxis(),
|
||||||
title: ChartTitle(text: 'Line Chart'),
|
// title: ChartTitle(text: 'Line Chart'),
|
||||||
legend: Legend(isVisible: true),
|
// legend: Legend(isVisible: true),
|
||||||
tooltipBehavior: TooltipBehavior(enable: true),
|
// tooltipBehavior: TooltipBehavior(enable: true),
|
||||||
series: <CartesianSeries<ChartData, String>>[
|
// series: <CartesianSeries<ChartData, String>>[
|
||||||
LineSeries<ChartData, String>(
|
// LineSeries<ChartData, String>(
|
||||||
dataSource: parseLineChartData(chartData['response']),
|
// dataSource: parseLineChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) => data.timePeriod ?? '',
|
// xValueMapper: (ChartData data, _) => data.timePeriod ?? '',
|
||||||
yValueMapper: (ChartData data, _) => data.value ?? 0.0,
|
// yValueMapper: (ChartData data, _) => data.value ?? 0.0,
|
||||||
name: 'Sales',
|
// name: 'Sales',
|
||||||
dataLabelSettings: DataLabelSettings(isVisible: true),
|
// dataLabelSettings: DataLabelSettings(isVisible: true),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
case 'bar':
|
// case 'bar':
|
||||||
return SfCartesianChart(
|
// return SfCartesianChart(
|
||||||
primaryXAxis: CategoryAxis(),
|
// primaryXAxis: CategoryAxis(),
|
||||||
title: ChartTitle(text: 'Bar Chart'),
|
// title: ChartTitle(text: 'Bar Chart'),
|
||||||
tooltipBehavior: TooltipBehavior(enable: true),
|
// tooltipBehavior: TooltipBehavior(enable: true),
|
||||||
series: <CartesianSeries<ChartData, String>>[
|
// series: <CartesianSeries<ChartData, String>>[
|
||||||
BarSeries<ChartData, String>(
|
// BarSeries<ChartData, String>(
|
||||||
dataSource: parseBarChartData(chartData['response']),
|
// dataSource: parseBarChartData(chartData['response']),
|
||||||
xValueMapper: (ChartData data, _) => data.timePeriod ?? '',
|
// xValueMapper: (ChartData data, _) => data.timePeriod ?? '',
|
||||||
yValueMapper: (ChartData data, _) => data.value ?? 0.0,
|
// yValueMapper: (ChartData data, _) => data.value ?? 0.0,
|
||||||
name: 'Gold',
|
// name: 'Gold',
|
||||||
color: Color.fromRGBO(8, 142, 255, 1),
|
// color: Color.fromRGBO(8, 142, 255, 1),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
default:
|
// default:
|
||||||
return Center(child: Text('Unknown chart type'));
|
// return Center(child: Text('Unknown chart type'));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@override
|
// @override
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
// return Scaffold(
|
||||||
backgroundColor: const Color(0xFF7DAFBC),
|
// backgroundColor: const Color(0xFF7DAFBC),
|
||||||
appBar: AppBar(
|
// appBar: AppBar(
|
||||||
backgroundColor: Color(0xFF7DAFBC),
|
// backgroundColor: Color(0xFF7DAFBC),
|
||||||
elevation: 0,
|
// elevation: 0,
|
||||||
leading: IconButton(
|
// leading: IconButton(
|
||||||
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
|
// icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
context.go('/myhomepage');
|
// context.go('/myhomepage');
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
title: Text(
|
// title: Text(
|
||||||
'Charts',
|
// 'Charts',
|
||||||
style: TextStyle(color: Colors.white),
|
// style: TextStyle(color: Colors.white),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
body: isLoading
|
// body: isLoading
|
||||||
? Center(child: CircularProgressIndicator())
|
// ? Center(child: CircularProgressIndicator())
|
||||||
: Column(
|
// : Column(
|
||||||
children: [
|
// children: [
|
||||||
// Row for two cards
|
// // Row for two cards
|
||||||
Row(
|
// Row(
|
||||||
children: [
|
// children: [
|
||||||
// First Card
|
// // First Card
|
||||||
Expanded(
|
// Expanded(
|
||||||
flex: 6,
|
// flex: 6,
|
||||||
child: Card(
|
// child: Card(
|
||||||
margin: EdgeInsets.all(10),
|
// margin: EdgeInsets.all(10),
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
// padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
Text(
|
// Text(
|
||||||
'Card 1',
|
// 'Card 1',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.bold),
|
// fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
// ),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Text('Content for Card 1 goes here.'),
|
// Text('Content for Card 1 goes here.'),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
// Second Card
|
// // Second Card
|
||||||
Expanded(
|
// Expanded(
|
||||||
flex: 6,
|
// flex: 6,
|
||||||
child: Card(
|
// child: Card(
|
||||||
margin: EdgeInsets.all(10),
|
// margin: EdgeInsets.all(10),
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
// padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
Text(
|
// Text(
|
||||||
'Card 2',
|
// 'Card 2',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.bold),
|
// fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
// ),
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Text('Content for Card 2 goes here.'),
|
// Text('Content for Card 2 goes here.'),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
// List of charts
|
// // List of charts
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: ListView.builder(
|
// child: ListView.builder(
|
||||||
itemCount: chartsData.length,
|
// itemCount: chartsData.length,
|
||||||
itemBuilder: (context, index) {
|
// itemBuilder: (context, index) {
|
||||||
return Card(
|
// return Card(
|
||||||
margin: EdgeInsets.all(10),
|
// margin: EdgeInsets.all(10),
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
// padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
SizedBox(height: 10),
|
// SizedBox(height: 10),
|
||||||
Container(
|
// Container(
|
||||||
height: 300,
|
// height: 300,
|
||||||
child: buildChart(chartsData[index]),
|
// child: buildChart(chartsData[index]),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
class ChartData {
|
// class ChartData {
|
||||||
final int? xInt; // For column and other charts, using int for x
|
// final int? xInt; // For column and other charts, using int for x
|
||||||
final DateTime? xDateTime; // For scatter charts, using DateTime for x
|
// final DateTime? xDateTime; // For scatter charts, using DateTime for x
|
||||||
final double y; // For column and other charts
|
// final double y; // For column and other charts
|
||||||
final String? timePeriod; // For line and bar charts
|
// final String? timePeriod; // For line and bar charts
|
||||||
final double? value; // For line and bar charts
|
// final double? value; // For line and bar charts
|
||||||
final double? y2; // For secondary data (stacked column chart)
|
// final double? y2; // For secondary data (stacked column chart)
|
||||||
final double? y3; // For tertiary data (stacked column chart)
|
// final double? y3; // For tertiary data (stacked column chart)
|
||||||
final double? y4; // For quaternary data (stacked column chart)
|
// final double? y4; // For quaternary data (stacked column chart)
|
||||||
|
//
|
||||||
// Constructor that handles all chart cases
|
// // Constructor that handles all chart cases
|
||||||
ChartData({
|
// ChartData({
|
||||||
this.xInt,
|
// this.xInt,
|
||||||
this.xDateTime,
|
// this.xDateTime,
|
||||||
this.y = 0.0,
|
// this.y = 0.0,
|
||||||
this.timePeriod,
|
// this.timePeriod,
|
||||||
this.value,
|
// this.value,
|
||||||
this.y2,
|
// this.y2,
|
||||||
this.y3,
|
// this.y3,
|
||||||
this.y4,
|
// this.y4,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|||||||
@ -37,6 +37,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
true
|
true
|
||||||
]; // One for each TextField
|
]; // One for each TextField
|
||||||
|
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
String _getControllerText(int index) {
|
String _getControllerText(int index) {
|
||||||
if (index == 0) return _usernameController.text;
|
if (index == 0) return _usernameController.text;
|
||||||
if (index == 1) return _emailController.text;
|
if (index == 1) return _emailController.text;
|
||||||
@ -169,6 +171,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
// Function to open the date picker
|
// Function to open the date picker
|
||||||
|
|
||||||
void _pickImage() async {
|
void _pickImage() async {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true; // Start loading
|
||||||
|
});
|
||||||
final XFile? pickedFile =
|
final XFile? pickedFile =
|
||||||
await _picker.pickImage(source: ImageSource.gallery);
|
await _picker.pickImage(source: ImageSource.gallery);
|
||||||
if (pickedFile != null) {
|
if (pickedFile != null) {
|
||||||
@ -179,6 +184,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
fileExtension == 'png' ||
|
fileExtension == 'png' ||
|
||||||
fileExtension == "heic") {
|
fileExtension == "heic") {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
_profileImage = File(pickedFile.path);
|
_profileImage = File(pickedFile.path);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -365,28 +371,68 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
// CircleAvatar(
|
||||||
radius: 50,
|
// radius: 50,
|
||||||
backgroundImage: _profileImage != null
|
// backgroundImage: _profileImage != null
|
||||||
? FileImage(_profileImage!)
|
// ? FileImage(_profileImage!)
|
||||||
: AssetImage("assets/edit_profile/profile.png")
|
// : AssetImage("assets/edit_profile/profile.png")
|
||||||
as ImageProvider,
|
// as ImageProvider,
|
||||||
child: Align(
|
// child: Align(
|
||||||
alignment: Alignment.bottomRight,
|
// alignment: Alignment.bottomRight,
|
||||||
child: GestureDetector(
|
// child: GestureDetector(
|
||||||
onTap: _pickImage, // Call `_pickImage` on tap
|
// onTap: _pickImage, // Call `_pickImage` on tap
|
||||||
child: CircleAvatar(
|
// child: CircleAvatar(
|
||||||
radius: 15,
|
// radius: 15,
|
||||||
backgroundColor: Colors.white,
|
// backgroundColor: Colors.white,
|
||||||
child: Icon(
|
// child: Icon(
|
||||||
Icons.camera_alt,
|
// Icons.camera_alt,
|
||||||
size: 15,
|
// size: 15,
|
||||||
color: Colors.grey,
|
// 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),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
|||||||
@ -160,9 +160,13 @@
|
|||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import '../../drawer_routes/custom_drawer_routes.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 StatefulWidget {
|
class MyHomePage extends StatefulWidget {
|
||||||
const MyHomePage({super.key});
|
const MyHomePage({super.key});
|
||||||
@ -171,18 +175,28 @@ class MyHomePage extends StatefulWidget {
|
|||||||
State<MyHomePage> createState() => _MyHomePageState();
|
State<MyHomePage> createState() => _MyHomePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleInfoCardClick(BuildContext context, String data) {
|
void handleInfoCardClick(BuildContext context, String data, Color color) {
|
||||||
// Handle navigation and pass dynamic data
|
// Handle navigation and pass dynamic data
|
||||||
print(data);
|
print(data);
|
||||||
final dataSets = data;
|
final dataSets = data;
|
||||||
print(dataSets);
|
if (dataSets != null) {
|
||||||
if (dataSets == 'hotels') {
|
// Perform navigation
|
||||||
context.go('/chartScreen/$dataSets');
|
|
||||||
} else if (dataSets == 'divorces') {
|
|
||||||
context.go('/chartScreen/$dataSets');
|
|
||||||
} else if (dataSets == 'marriages') {
|
|
||||||
context.go('/chartScreen/$dataSets');
|
context.go('/chartScreen/$dataSets');
|
||||||
|
} else {
|
||||||
|
// Show error if dataSet is null
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text('No dataset available')),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
// final dataSets = data;
|
||||||
|
// print(dataSets);
|
||||||
|
// if (dataSets == 'hotels') {
|
||||||
|
// context.go('/chartScreen/$dataSets');
|
||||||
|
// } else if (dataSets == 'divorces') {
|
||||||
|
// context.go('/chartScreen/$dataSets');
|
||||||
|
// } else if (dataSets == 'marriages') {
|
||||||
|
// context.go('/Chart/$dataSets');
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
@ -191,243 +205,242 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
double mywidth = MediaQuery.of(context).size.width;
|
double mywidth = MediaQuery.of(context).size.width;
|
||||||
return BaseScaffold(
|
return BaseScaffold(
|
||||||
mycenterTitle: true,
|
title: Center(
|
||||||
title: SizedBox(
|
child: SizedBox(
|
||||||
height: myheight / 5,
|
height: myheight / 5,
|
||||||
width: mywidth / 3,
|
width: mywidth / 3,
|
||||||
child: Image(image: AssetImage('assets/logos/uae_stat.png'))),
|
child: Image(image: AssetImage('assets/logos/uae_stat.png')))),
|
||||||
body: EconomyStats(),
|
body: EconomyStatsWidget(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EconomyStats extends StatelessWidget {
|
class EconomyStatsWidget extends StatefulWidget {
|
||||||
const EconomyStats({Key? key}) : super(key: key);
|
const EconomyStatsWidget({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
EconomyStatsState createState() => EconomyStatsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class EconomyStatsState extends State<EconomyStatsWidget> {
|
||||||
|
List<dynamic> data = [];
|
||||||
|
|
||||||
|
bool isLoading = true;
|
||||||
|
|
||||||
|
void initState() {
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> fetchData() async {
|
||||||
|
const baseUrl = 'https://pb.venbait.in/api/getHomePageData';
|
||||||
|
try {
|
||||||
|
final response = await http.get(Uri.parse(baseUrl));
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
setState(() {
|
||||||
|
data = json.decode(response.body);
|
||||||
|
print("HomeDAta $data");
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw Exception('Failed to load data');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
print('Error fetching data: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
child: Padding(
|
double mywidth = MediaQuery.of(context).size.width;
|
||||||
padding: EdgeInsets.only(left: 10, right: 10),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
// Header Section
|
|
||||||
RoundedCornerContainer(
|
|
||||||
text: 'ECONOMY',
|
|
||||||
backgroundColor: Color(0xFF7DAFBC),
|
|
||||||
textStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Grid Section
|
|
||||||
|
|
||||||
// ECONOMY DETAILS
|
return Expanded(
|
||||||
Padding(
|
child: Container(
|
||||||
padding: const EdgeInsets.only(
|
height: myheight,
|
||||||
top: 10,
|
// color: Colors.cyan,
|
||||||
),
|
child: Padding(
|
||||||
child: Column(
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
children: [
|
child: Column(
|
||||||
// First Row
|
children: data.map((mainTopic) {
|
||||||
Row(
|
String colorPattern = mainTopic['color_pattern'];
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
Color backgroundColor = Color(int.parse(colorPattern));
|
||||||
|
Color borderColor =
|
||||||
|
backgroundColor; // Use the same color for the border
|
||||||
|
|
||||||
|
// final totalTiles = mainTopic['sub_topics']
|
||||||
|
// .expand((subTopic) => (subTopic['tile_data'] as List<dynamic>? ?? []))
|
||||||
|
// .length;
|
||||||
|
|
||||||
|
final totalTiles =
|
||||||
|
(mainTopic['tile_data'] as List<dynamic>?)?.length ?? 0;
|
||||||
|
|
||||||
|
// Compute crossAxisCount dynamically
|
||||||
|
final crossAxisCount =
|
||||||
|
(totalTiles / 2).ceil(); // Divide by 2 and round up
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
child: Container(
|
||||||
|
// color: Colors.cyan,
|
||||||
|
height:
|
||||||
|
myheight, // Set the background color for the entire Column
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
InfoCard(
|
RoundedCornerContainer(
|
||||||
title: 'GDP (Constant)',
|
text: mainTopic['main_topic'],
|
||||||
subtitle: '(2022) (AED)',
|
backgroundColor: backgroundColor,
|
||||||
value: '1.62T',
|
textStyle: const TextStyle(
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
fontSize: 24,
|
||||||
textcolor: Color(0xFF7DAFBC),
|
fontWeight: FontWeight.w500,
|
||||||
onTap: () => handleInfoCardClick(context, 'Inflation'),
|
color: Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
InfoCard(
|
SizedBox(
|
||||||
title: 'Inflation Rate',
|
height: myheight / 4.8, // Set dynamic height
|
||||||
subtitle: '(2022)',
|
child: Container(
|
||||||
value: '4.82%',
|
// color: Colors.grey[200], // Set a background color for the scrollable container
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
child: ConstrainedBox(
|
||||||
textcolor: Color(0xFF7DAFBC),
|
constraints: BoxConstraints(
|
||||||
onTap: () => handleInfoCardClick(context, 'Inflation'),
|
maxWidth: MediaQuery.of(context).size.width * 2,
|
||||||
|
),
|
||||||
|
child: MasonryGridView.builder(
|
||||||
|
gridDelegate:
|
||||||
|
SliverSimpleGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: crossAxisCount,
|
||||||
|
),
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: totalTiles,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final tileDataList = (mainTopic['tile_data']
|
||||||
|
as List<dynamic>?) ??
|
||||||
|
[];
|
||||||
|
final tileData = Map<String, String>.from(
|
||||||
|
tileDataList[index]);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.all(0),
|
||||||
|
height: myheight /
|
||||||
|
9.2, // Variable height for tiles
|
||||||
|
width: mywidth / 3,
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(bottom: 3, top: 3),
|
||||||
|
// color: Colors.yellowAccent.shade100, // Tile background color
|
||||||
|
child: Flexible(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: _buildRows(
|
||||||
|
[tileData],
|
||||||
|
borderColor,
|
||||||
|
mainTopic['color_pattern']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
),
|
||||||
// Second Row
|
);
|
||||||
Row(
|
}).toList(),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
),
|
||||||
children: [
|
|
||||||
InfoCard(
|
|
||||||
title: 'Trade Value',
|
|
||||||
subtitle: '(Jan - Jan 2024) - AED',
|
|
||||||
value: '215.4B',
|
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
|
||||||
textcolor: Color(0xFF7DAFBC),
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'commodities'),
|
|
||||||
),
|
|
||||||
InfoCard(
|
|
||||||
title: 'Hotel Guests',
|
|
||||||
subtitle: '(2022)',
|
|
||||||
value: '25.21M',
|
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
|
||||||
textcolor: Color(0xFF7DAFBC),
|
|
||||||
onTap: () => handleInfoCardClick(context, 'hotels'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
RoundedCornerContainer(
|
|
||||||
text: 'SOCIAL',
|
|
||||||
backgroundColor: Colors.brown[200]!,
|
|
||||||
textStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// SOCIAL DETAILS
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 10,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
// First Row
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
InfoCard(
|
|
||||||
title: 'Divorces',
|
|
||||||
subtitle: '(2022)',
|
|
||||||
value: '0',
|
|
||||||
bordercolor: Colors.brown[200]!,
|
|
||||||
textcolor: Colors.brown[200]!,
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'divorces'),
|
|
||||||
),
|
|
||||||
InfoCard(
|
|
||||||
title: 'Marriages',
|
|
||||||
subtitle: '(2022)',
|
|
||||||
value: '0',
|
|
||||||
bordercolor: Colors.brown[200]!,
|
|
||||||
textcolor: Colors.brown[200]!,
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'marriages'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
// Second Row
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
InfoCard(
|
|
||||||
title: 'Hospitals (Gov)',
|
|
||||||
subtitle: '(Jan - Jan 2024) - AED',
|
|
||||||
value: '215.4B',
|
|
||||||
bordercolor: Colors.brown[200]!,
|
|
||||||
textcolor: Colors.brown[200]!,
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'Hospitals'),
|
|
||||||
),
|
|
||||||
InfoCard(
|
|
||||||
title: 'Schools',
|
|
||||||
subtitle: '(2022)',
|
|
||||||
value: '25.21M',
|
|
||||||
bordercolor: Colors.brown[200]!,
|
|
||||||
textcolor: Colors.brown[200]!,
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'Schools'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
RoundedCornerContainer(
|
|
||||||
text: 'ENVIRONMENT',
|
|
||||||
backgroundColor: Color(0xFF7DAFBC),
|
|
||||||
textStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// ENVIRONMENT DETAILS
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 10,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
// First Row
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
InfoCard(
|
|
||||||
title: 'Electricity',
|
|
||||||
subtitle: '(2022) (AED)',
|
|
||||||
value: '1.62T',
|
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
|
||||||
textcolor: Color(0xFF7DAFBC),
|
|
||||||
onTap: () => handleInfoCardClick(
|
|
||||||
context, 'Electricity'),
|
|
||||||
),
|
|
||||||
InfoCard(
|
|
||||||
title: 'Cruid oil',
|
|
||||||
subtitle: '(2022)',
|
|
||||||
value: '4.82%',
|
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
|
||||||
textcolor: Color(0xFF7DAFBC),
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'Cruid'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
// Second Row
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
InfoCard(
|
|
||||||
title: 'Export of oil',
|
|
||||||
subtitle: '(Jan - Jan 2024) - AED',
|
|
||||||
value: '215.4B',
|
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
|
||||||
textcolor: Color(0xFF7DAFBC),
|
|
||||||
onTap: () =>
|
|
||||||
handleInfoCardClick(context, 'Export'),
|
|
||||||
),
|
|
||||||
InfoCard(
|
|
||||||
title: 'Desalinated water',
|
|
||||||
subtitle: '(2022)',
|
|
||||||
value: '25.21M',
|
|
||||||
bordercolor: Color(0xFF7DAFBC),
|
|
||||||
textcolor: Color(0xFF7DAFBC),
|
|
||||||
onTap: () => handleInfoCardClick(
|
|
||||||
context, 'Desalinated'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// List<Widget> _buildRows(List<Map<String, String>> tileData, Color borderColor) {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// List<Widget> rows = [];
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < tileData.length; i += 2) {
|
||||||
|
// // Adding a row for every two items
|
||||||
|
// rows.add(
|
||||||
|
// Container(
|
||||||
|
// // color: Colors.grey[200], // Set background color for the row
|
||||||
|
// // padding: EdgeInsets.symmetric(vertical: 7.0), // Optional padding
|
||||||
|
// padding: EdgeInsets.only(top:5, bottom:2),
|
||||||
|
// child: Expanded(
|
||||||
|
// child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
// children: tileData
|
||||||
|
// .sublist(i, i + 2 > tileData.length ? tileData.length : i + 2)
|
||||||
|
// .map((tile) {
|
||||||
|
// return Expanded(
|
||||||
|
// child: InfoCard(
|
||||||
|
// title: tile['data_set_tile_heading']!,
|
||||||
|
// subtitle: tile['value_source']!,
|
||||||
|
// value: tile['value']!,
|
||||||
|
// dataset:tile['data_set']!,
|
||||||
|
// bordercolor: borderColor,
|
||||||
|
// textcolor: borderColor,
|
||||||
|
// backgroundColor: Colors.white, // Set background color for InfoCard
|
||||||
|
// onTap: () => {},
|
||||||
|
//
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }).toList(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// // rows.add(SizedBox(height: 1)); // Add space between rows
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return rows;
|
||||||
|
// }
|
||||||
|
|
||||||
|
List<Widget> _buildRows(
|
||||||
|
List<Map<String, dynamic>> tileData, Color borderColor, color_pattern) {
|
||||||
|
// Sort the tileData list based on 'data_set_list_order'
|
||||||
|
// tileData.sort((a, b) => a['data_set_list_order'].compareTo(b['data_set_list_order']));
|
||||||
|
tileData.sort((a, b) =>
|
||||||
|
(a['data_set_list_order'] ?? 0).compareTo(b['data_set_list_order'] ?? 0));
|
||||||
|
|
||||||
|
List<Widget> rows = [];
|
||||||
|
print('tileDataLength: $tileData.length');
|
||||||
|
|
||||||
|
for (int i = 0; i < tileData.length; i += 2) {
|
||||||
|
// Adding a row for every two items
|
||||||
|
rows.add(
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 5, bottom: 2),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: tileData
|
||||||
|
.sublist(i, i + 2 > tileData.length ? tileData.length : i + 2)
|
||||||
|
.map((tile) {
|
||||||
|
return Expanded(
|
||||||
|
child: InfoCard(
|
||||||
|
title: tile['data_set_tile_heading']!,
|
||||||
|
subtitle: tile['value_source']!,
|
||||||
|
value: tile['value']!,
|
||||||
|
dataset: tile['data_set']!,
|
||||||
|
bordercolor: borderColor,
|
||||||
|
textcolor: borderColor,
|
||||||
|
backgroundColor:
|
||||||
|
Colors.white, // Set background color for InfoCard
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
class RoundedCornerContainer extends StatelessWidget {
|
class RoundedCornerContainer extends StatelessWidget {
|
||||||
final String text;
|
final String text;
|
||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
@ -445,7 +458,7 @@ class RoundedCornerContainer extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
borderRadius: BorderRadius.circular(12), // Rounded corners
|
borderRadius: BorderRadius.circular(16), // Rounded corners
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -466,18 +479,22 @@ class InfoCard extends StatelessWidget {
|
|||||||
final String title;
|
final String title;
|
||||||
final String subtitle;
|
final String subtitle;
|
||||||
final String value;
|
final String value;
|
||||||
|
final String dataset;
|
||||||
final Color bordercolor;
|
final Color bordercolor;
|
||||||
final Color? textcolor;
|
final Color? textcolor;
|
||||||
final VoidCallback onTap; // New callback parameter
|
final VoidCallback onTap;
|
||||||
|
final Color backgroundColor;
|
||||||
|
|
||||||
const InfoCard({
|
const InfoCard({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.subtitle,
|
required this.subtitle,
|
||||||
required this.value,
|
required this.value,
|
||||||
|
required this.dataset,
|
||||||
required this.bordercolor,
|
required this.bordercolor,
|
||||||
this.textcolor,
|
this.textcolor,
|
||||||
required this.onTap, // Initialize in constructor
|
required this.onTap,
|
||||||
|
required this.backgroundColor,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -485,50 +502,84 @@ class InfoCard extends StatelessWidget {
|
|||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
double mywidth = MediaQuery.of(context).size.width;
|
double mywidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
return Expanded(
|
return GestureDetector(
|
||||||
child: GestureDetector(
|
onTap: () {
|
||||||
onTap: onTap, // Use callback for handling clicks
|
// Call handleInfoCardClick and pass the title and color
|
||||||
child: Container(
|
handleInfoCardClick(
|
||||||
height: myheight / 9,
|
context, dataset, bordercolor); // Pass 'title' to the function
|
||||||
width: mywidth / 4,
|
},
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 8),
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
height: myheight / 12,
|
||||||
border: Border.all(color: bordercolor),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
width: mywidth / 4,
|
||||||
),
|
|
||||||
child: Column(
|
margin: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
mainAxisSize: MainAxisSize.min,
|
// padding: const EdgeInsets.all(10),
|
||||||
children: [
|
padding: const EdgeInsets.only(bottom: 1, top: 1, left: 10, right: 10),
|
||||||
Expanded(
|
decoration: BoxDecoration(
|
||||||
child: Text(
|
border: Border.all(color: bordercolor),
|
||||||
title,
|
borderRadius: BorderRadius.circular(8),
|
||||||
style: const TextStyle(
|
),
|
||||||
fontSize: 16,
|
child: Column(
|
||||||
fontWeight: FontWeight.bold,
|
mainAxisSize: MainAxisSize.min,
|
||||||
color: Colors.black,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
child: FittedBox(
|
||||||
|
fit: BoxFit.contain, // Adjust text to fit within the bounds
|
||||||
|
child: Padding(
|
||||||
|
// padding: const EdgeInsets.all(4.0),
|
||||||
|
padding: const EdgeInsets.only(top: 4, bottom: 0),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
),
|
||||||
Text(
|
const SizedBox(height: 0.5),
|
||||||
subtitle,
|
|
||||||
textAlign: TextAlign.center,
|
Flexible(
|
||||||
style: const TextStyle(
|
fit: FlexFit.loose,
|
||||||
fontSize: 12,
|
child: FittedBox(
|
||||||
color: Colors.grey,
|
fit: BoxFit.contain,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
subtitle,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 8,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
),
|
||||||
Text(
|
const SizedBox(height: 1),
|
||||||
value,
|
|
||||||
style: TextStyle(
|
// Flexible(
|
||||||
fontSize: 24,
|
// fit: FlexFit.loose,
|
||||||
fontWeight: FontWeight.bold,
|
// child: FittedBox(
|
||||||
color: textcolor ?? Colors.black,
|
// fit: BoxFit.scaleDown,
|
||||||
),
|
// child:
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: textcolor ?? Colors.black,
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
final _pb = PocketBase('https://pb.venbait.in');
|
final _pb = PocketBase('https://pb.venbait.in');
|
||||||
// final _pb = PocketBase('http://127.0.0.1:8090');
|
// final _pb = PocketBase('http://127.0.0.1:8090');
|
||||||
bool _isProfileCompleted = false;
|
bool _isProfileCompleted = false;
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
// Add focus nodes and hint states
|
// Add focus nodes and hint states
|
||||||
final List<FocusNode> _focusNodes = List.generate(4, (_) => FocusNode());
|
final List<FocusNode> _focusNodes = List.generate(4, (_) => FocusNode());
|
||||||
@ -207,16 +208,30 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
// Function to open the date picker
|
// Function to open the date picker
|
||||||
|
|
||||||
void _pickImage() async {
|
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 =
|
final XFile? pickedFile =
|
||||||
await _picker.pickImage(source: ImageSource.gallery);
|
await _picker.pickImage(source: ImageSource.gallery);
|
||||||
if (pickedFile != null) {
|
if (pickedFile != null) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true; // Start loading
|
||||||
|
});
|
||||||
|
print(pickedFile);
|
||||||
final String fileExtension =
|
final String fileExtension =
|
||||||
pickedFile.path.split('.').last.toLowerCase();
|
pickedFile.path.split('.').last.toLowerCase();
|
||||||
|
print('fileExtension $fileExtension');
|
||||||
if (fileExtension == 'jpg' ||
|
if (fileExtension == 'jpg' ||
|
||||||
fileExtension == 'jpeg' ||
|
fileExtension == 'jpeg' ||
|
||||||
fileExtension == 'png' ||
|
fileExtension == 'png' ||
|
||||||
fileExtension == "heic") {
|
fileExtension == "heic") {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
_profileImage = File(pickedFile.path);
|
_profileImage = File(pickedFile.path);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -225,6 +240,10 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false; // Hide loader
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _pickDate() async {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseScaffold(
|
return BaseScaffold(
|
||||||
@ -385,34 +415,112 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
// CircleAvatar(
|
||||||
radius: 50,
|
// radius: 50,
|
||||||
backgroundImage: _profileImage != null
|
// backgroundImage: _profileImage != null
|
||||||
? FileImage(
|
// ? FileImage(
|
||||||
_profileImage!) // If a local file is selected
|
// _profileImage!) // If a local file is selected
|
||||||
: _avatarUrl.isNotEmpty
|
// : _avatarUrl.isNotEmpty
|
||||||
? NetworkImage(_avatarUrl) // Load from URL
|
// ? NetworkImage(_avatarUrl) // Load from URL
|
||||||
: AssetImage(
|
// : AssetImage(
|
||||||
"assets/edit_profile/profile.png")
|
// "assets/edit_profile/profile.png")
|
||||||
as ImageProvider,
|
// 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,
|
Stack(
|
||||||
child: Align(
|
alignment: Alignment.center,
|
||||||
alignment: Alignment.bottomRight,
|
children: [
|
||||||
child: GestureDetector(
|
CircleAvatar(
|
||||||
onTap: _pickImage, // Call `_pickImage` on tap
|
radius: 50,
|
||||||
child: CircleAvatar(
|
backgroundImage: _profileImage != null
|
||||||
radius: 15,
|
? FileImage(
|
||||||
backgroundColor: Colors.white,
|
_profileImage!) // If a local file is selected
|
||||||
child: Icon(
|
: _avatarUrl.isNotEmpty
|
||||||
Icons.camera_alt,
|
? NetworkImage(
|
||||||
size: 15,
|
_avatarUrl) // Load from URL
|
||||||
color: Colors.grey,
|
: 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),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
|||||||
@ -527,7 +527,7 @@ class _FeedbackFormState extends State<FeedbackForm>
|
|||||||
)),
|
)),
|
||||||
RatingBar.builder(
|
RatingBar.builder(
|
||||||
initialRating: rating,
|
initialRating: rating,
|
||||||
minRating: 1,
|
minRating: 0,
|
||||||
direction: Axis.horizontal,
|
direction: Axis.horizontal,
|
||||||
allowHalfRating: true,
|
allowHalfRating: true,
|
||||||
itemCount: 5,
|
itemCount: 5,
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
|||||||
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
|
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
|
||||||
return User(
|
return User(
|
||||||
id: record.id, // Correctly passing the ID
|
id: record.id, // Correctly passing the ID
|
||||||
userName: record.getStringValue('username'),
|
userName: record.getStringValue('uname'),
|
||||||
emailId: record.getStringValue('email'),
|
emailId: record.getStringValue('email'),
|
||||||
registrationDate: formattedDate,
|
registrationDate: formattedDate,
|
||||||
status: record.getStringValue('status'),
|
status: record.getStringValue('status'),
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:pocketbase/pocketbase.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class BaseScaffold extends StatelessWidget {
|
class BaseScaffold extends StatefulWidget {
|
||||||
final Widget body;
|
final Widget body;
|
||||||
final Widget title;
|
final Widget title;
|
||||||
final bool ? showBackButton;
|
final bool? showBackButton;
|
||||||
final bool ? mycenterTitle;
|
final bool? mycenterTitle;
|
||||||
final List<Widget>? actions;
|
final List<Widget>? actions;
|
||||||
final Color? appbarColor, mytitleColor;
|
final Color? appbarColor, mytitleColor;
|
||||||
|
|
||||||
@ -15,76 +17,126 @@ class BaseScaffold extends StatelessWidget {
|
|||||||
required this.title,
|
required this.title,
|
||||||
this.actions,
|
this.actions,
|
||||||
this.showBackButton = false,
|
this.showBackButton = false,
|
||||||
this.mycenterTitle = false, this.appbarColor, this.mytitleColor
|
this.mycenterTitle = false,
|
||||||
|
this.appbarColor,
|
||||||
|
this.mytitleColor,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
// final Widget body;
|
|
||||||
//
|
@override
|
||||||
// const BaseScaffold({required this.body});
|
_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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Get the current route to highlight the active item
|
|
||||||
String currentRoute = GoRouterState.of(context).matchedLocation;
|
String currentRoute = GoRouterState.of(context).matchedLocation;
|
||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
double mywidth = MediaQuery.of(context).size.width;
|
double mywidth = MediaQuery.of(context).size.width;
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(title: title, backgroundColor : appbarColor,actions: [
|
|
||||||
IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
|
|
||||||
],
|
|
||||||
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: [
|
children: [
|
||||||
// Show the back button if showBackButton is true
|
if (widget.showBackButton == true)
|
||||||
if (showBackButton == true)
|
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 15,
|
left: 15,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
icon: Icon(Icons.arrow_back_ios_new),
|
icon: const Icon(Icons.arrow_back_ios_new),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Show the drawer icon in all cases
|
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 10,
|
right: 10,
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
color: (showBackButton == true) ? Colors.white : Colors.black,
|
color: (widget.showBackButton == true)
|
||||||
icon: Icon(Icons.menu),
|
? Colors.white
|
||||||
|
: Colors.black,
|
||||||
|
icon: const Icon(Icons.menu),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Open the drawer using the Scaffold context
|
|
||||||
Scaffold.of(context).openDrawer();
|
Scaffold.of(context).openDrawer();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -92,14 +144,12 @@ class BaseScaffold extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
drawer: Drawer(
|
drawer: Drawer(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
DrawerHeader(
|
DrawerHeader(
|
||||||
//decoration: BoxDecoration(color: Colors.blue),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
@ -117,18 +167,39 @@ class BaseScaffold extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: mywidth / 8,
|
width: mywidth / 8,
|
||||||
child: Image(
|
height: mywidth / 8,
|
||||||
image: AssetImage(
|
child: ClipOval(
|
||||||
'assets/edit_profile/profile.png'))),
|
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(
|
SizedBox(
|
||||||
width: mywidth / 20,
|
width: mywidth / 20,
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text('Mohammad'),
|
// Text(userId ?? 'Loading user...'), // Display userId here
|
||||||
Text('Mohammad@fcsc.com')
|
// Text('Mohammad@fcsc.com')
|
||||||
|
Text(userName ?? 'Loading...'),
|
||||||
|
Text(
|
||||||
|
userEmail ?? 'Loading...',
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -138,33 +209,26 @@ class BaseScaffold extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: SizedBox(
|
leading: Icon(Icons.feedback),
|
||||||
height: myheight / 15,
|
title: const Text('Feedback'),
|
||||||
width: mywidth / 15,
|
|
||||||
child: Image(
|
|
||||||
image: AssetImage('assets/icons/drawer/message.png'))),
|
|
||||||
title: Text('Feedback'),
|
|
||||||
onTap: () => context.go('/feedback'),
|
onTap: () => context.go('/feedback'),
|
||||||
),
|
),
|
||||||
|
if (role == 'admin')
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.manage_accounts),
|
||||||
|
title: const Text('Manage User'),
|
||||||
|
onTap: () => context.go('/manageuser'),
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: SizedBox(
|
leading: Icon(Icons.book),
|
||||||
height: myheight / 15,
|
title: const Text('User Guide'),
|
||||||
width: mywidth / 15,
|
|
||||||
child: Image(
|
|
||||||
image: AssetImage('assets/icons/drawer/manageuser.png'))),
|
|
||||||
title: Text('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'),
|
|
||||||
onTap: () => context.go('/user-guide'),
|
onTap: () => context.go('/user-guide'),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.logout),
|
||||||
|
title: const Text('Logout'),
|
||||||
|
onTap: () => context.go('/'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -174,49 +238,33 @@ class BaseScaffold extends StatelessWidget {
|
|||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
items: [
|
items: [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: SizedBox(
|
icon: Icon(Icons.home),
|
||||||
height: myheight / 15,
|
|
||||||
width: mywidth / 15,
|
|
||||||
child: Image(
|
|
||||||
image: AssetImage('assets/icons/bottom_bar/home.png'))),
|
|
||||||
label: 'Home',
|
label: 'Home',
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: SizedBox(
|
icon: Icon(Icons.map),
|
||||||
height: myheight / 15,
|
|
||||||
width: mywidth / 15,
|
|
||||||
child: Image(
|
|
||||||
image: AssetImage('assets/icons/bottom_bar/uae_map.png'))),
|
|
||||||
label: 'UAE Numbers',
|
label: 'UAE Numbers',
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: SizedBox(
|
icon: Icon(Icons.bar_chart),
|
||||||
height: myheight / 15,
|
label: 'Competitiveness',
|
||||||
width: mywidth / 15,
|
),
|
||||||
child: Image(
|
|
||||||
image:
|
|
||||||
AssetImage('assets/icons/bottom_bar/ranking.png'))),
|
|
||||||
label: 'Competitiveness'),
|
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: SizedBox(
|
icon: Icon(Icons.public),
|
||||||
height: myheight / 15,
|
label: 'Country Profile',
|
||||||
width: mywidth / 15,
|
),
|
||||||
child: Image(
|
|
||||||
image: AssetImage('assets/icons/bottom_bar/globe.png'))),
|
|
||||||
label: 'Country Profile'),
|
|
||||||
],
|
],
|
||||||
selectedItemColor: Colors.black,
|
selectedItemColor: Colors.black,
|
||||||
unselectedItemColor: Colors.grey,
|
unselectedItemColor: Colors.grey,
|
||||||
showUnselectedLabels: true,
|
showUnselectedLabels: true,
|
||||||
),
|
),
|
||||||
body: body,
|
body: widget.body,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Map the current route to the selected index
|
|
||||||
int _getSelectedIndex(String route) {
|
int _getSelectedIndex(String route) {
|
||||||
switch (route) {
|
switch (route) {
|
||||||
case '/':
|
case '/myhomepage':
|
||||||
return 0;
|
return 0;
|
||||||
case '/uaenumbers':
|
case '/uaenumbers':
|
||||||
return 1;
|
return 1;
|
||||||
@ -229,11 +277,10 @@ class BaseScaffold extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Handle navigation when an item is tapped
|
|
||||||
void _onItemTapped(BuildContext context, int index) {
|
void _onItemTapped(BuildContext context, int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
context.go('/');
|
context.go('/myhomepage');
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
context.go('/uaenumbers');
|
context.go('/uaenumbers');
|
||||||
|
|||||||
42
pubspec.lock
42
pubspec.lock
@ -385,10 +385,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: fl_chart
|
name: fl_chart
|
||||||
sha256: "10ddaf334fe84d59333a12d153043e366f243e0bdfff2df0313e1e249f5bf926"
|
sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.70.1"
|
version: "0.69.2"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -440,7 +440,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.4"
|
version: "2.4.4"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e"
|
sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e"
|
||||||
@ -467,10 +467,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage
|
name: flutter_secure_storage
|
||||||
sha256: "1913841ac4c7bf57cd2e05b717e1fbff7841b542962feff827b16525a781b3e4"
|
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.2.3"
|
version: "9.2.4"
|
||||||
flutter_secure_storage_linux:
|
flutter_secure_storage_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -661,10 +661,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: aa6f1280b670861ac45220cc95adc59bb6ae130259d36f980ccb62220dc5e59f
|
sha256: b62d34a506e12bb965e824b6db4fbf709ee4589cf5d3e99b45ab2287b008ee0c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+19"
|
version: "0.8.12+20"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1116,10 +1116,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
|
sha256: bf808be89fe9dc467475e982c1db6c2faf3d2acf54d526cd5ec37d86c99dbd84
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "2.4.1"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1260,22 +1260,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
syncfusion_flutter_charts:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: syncfusion_flutter_charts
|
|
||||||
sha256: b2a9f0fd585ef96c081c37697b46d48d3b0f3fe6bddc5011a3542962814fafa8
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "28.1.33"
|
|
||||||
syncfusion_flutter_core:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: syncfusion_flutter_core
|
|
||||||
sha256: "12735505d616320aebe39a6fc90b6608a09116378d66aee9636b0eddf7b75971"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "28.1.38"
|
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1376,18 +1360,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_web
|
name: url_launcher_web
|
||||||
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
|
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.3"
|
version: "2.4.0"
|
||||||
url_launcher_windows:
|
url_launcher_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_windows
|
name: url_launcher_windows
|
||||||
sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
|
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.4"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -21,7 +21,7 @@ dependencies:
|
|||||||
riverpod_annotation: ^2.3.3
|
riverpod_annotation: ^2.3.3
|
||||||
cupertino_icons: ^1.0.6
|
cupertino_icons: ^1.0.6
|
||||||
|
|
||||||
fl_chart: ^0.70.1
|
fl_chart: ^0.69.2
|
||||||
|
|
||||||
marquee: ^2.2.3
|
marquee: ^2.2.3
|
||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.1
|
||||||
@ -57,9 +57,9 @@ dependencies:
|
|||||||
provider: ^6.1.2
|
provider: ^6.1.2
|
||||||
mailer: ^6.2.0
|
mailer: ^6.2.0
|
||||||
image_picker: ^1.1.2
|
image_picker: ^1.1.2
|
||||||
syncfusion_flutter_charts: 28.1.33
|
|
||||||
material_charts: ^0.0.23
|
material_charts: ^0.0.23
|
||||||
flutter_staggered_grid_view: ^0.7.0
|
flutter_staggered_grid_view: ^0.7.0
|
||||||
|
flutter_plugin_android_lifecycle: ^2.0.24
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
fading_edge_scrollview: ^4.1.1
|
fading_edge_scrollview: ^4.1.1
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user