user guide

This commit is contained in:
Kalonkarthik 2025-01-08 10:29:59 +05:30
commit fe8632946c
15 changed files with 2441 additions and 169 deletions

View File

@ -26,11 +26,11 @@ if (flutterVersionName == null) {
android {
namespace = "ae.gov.fcsc.frontend"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
// ndkVersion = flutter.ndkVersion
ndkVersion = "25.1.8937393"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
defaultConfig {

View File

@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
org.gradle.java.home=C:\\Program Files\\Eclipse Adoptium\\jdk-17.0.13.11-hotspot
org.gradle.java.home=C:/Program Files/Eclipse Adoptium/jdk-21.0.5.11-hotspot

View File

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

View File

@ -18,8 +18,9 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
id "com.android.application" version "8.2.1" apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}
include ":app"

View File

@ -294,7 +294,11 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/competitiveness.dart';
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/country_profile.dart';
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/uae_numbers.dart';
import 'package:uae_stat/presentation/Screens/auth_verification/registration.dart';
import 'package:uae_stat/presentation/Screens/demo_home2.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/getting_started.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
@ -303,6 +307,8 @@ import '../presentation/Screens/auth_verification/changepassword.dart';
import '../presentation/Screens/auth_verification/confirm_password.dart';
import '../presentation/Screens/auth_verification/create_new_pw.dart';
import '../presentation/Screens/auth_verification/otp_verification.dart';
import '../presentation/Screens/charts/chart.dart';
import '../presentation/Screens/demo_home.dart';
import '../presentation/Screens/profilepage.dart';
import '../presentation/routes/auth_routes/login_route.dart';
import '../presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
@ -317,8 +323,13 @@ final GoRouter router = GoRouter(
routes: [
GoRoute(
path: '/',
//builder: (context, state) => LoginRoute(),
builder: (context, state) => LoginRoute(),
// builder: (context, state) => MyHomePage(),
),
GoRoute(
path: '/login',
builder: (context, state) => LoginRoute(),
//builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/myhomepage',
@ -328,6 +339,22 @@ final GoRouter router = GoRouter(
path: '/register',
builder: (context, state) => RegisterScreen(),
),
GoRoute(
path: '/DemoHome/:dataSets',
builder: (context, state) {
final dataSets = state.pathParameters['dataSets']!;
print('Router $dataSets');
return ChartPage(dataSets: dataSets);
},
),
GoRoute(
path: '/Chart/:dataSets',
builder: (context, state) {
final dataSets = state.pathParameters['dataSets']!;
print('Router $dataSets');
return ChartScreen(dataSets: dataSets);
},
),
GoRoute(
path: '/mailverification',
builder: (context, state) => EmailVerificationScreen(
@ -410,5 +437,21 @@ final GoRouter router = GoRouter(
path: '/manageuser',
builder: (context, state) => ManageUserRouter(),
),
// Bottom Navigation Routes
GoRoute(
path: '/uaenumbers',
builder: (context, state) => UaeNumbers(),
),
GoRoute(
path: '/competitiveness',
builder: (context, state) => Competitiveness(),
),
GoRoute(
path: '/countryprofile',
builder: (context, state) => CountryProfile(),
),
],
);

View File

@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
class Competitiveness extends StatelessWidget {
const Competitiveness({super.key});
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold(
title: Center(
child: SizedBox(
height: myheight / 5,
width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png')))),
body: CompetitivenessState(context),
);
}
Widget CompetitivenessState(BuildContext context) {return Center(child: Text("Competitiveness"));}
}

View File

@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
class CountryProfile extends StatelessWidget {
const CountryProfile({super.key});
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold(
title: Center(
child: SizedBox(
height: myheight / 5,
width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png')))),
body: CountryProfileWidget()
);
}
}
class CountryProfileWidget extends StatelessWidget {
const CountryProfileWidget({super.key});
@override
Widget build(BuildContext context) {
return Center(child: Text("COuntry Profile"),);
}
}

View File

@ -0,0 +1,292 @@
import 'package:flutter/material.dart';
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/components/constant/constant.dart';
class UaeNumbers extends StatelessWidget {
const UaeNumbers({super.key});
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold(
title: Text("UAE Numbers"),
body:
//EconomicDashboard(),
//EconomyExpandTile()
uaenumberWidget());
}
}
class uaenumberWidget extends StatelessWidget {
const uaenumberWidget({super.key});
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30.0),
border: Border.all(width: 1)
),
child: TextField(
decoration: InputDecoration(
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
),
),
),
SizedBox(height: myheight/35,),
CustomExpandableTile(
title: 'ECONOMY',
titleBackgroundColor: economyColor,
children: [
buildCategoryTitle('National Accounts',economyColor),
buildCardRow([
buildCard(context,'GDP (Constant)', '1.62T', '2022 (AED)',economyColor,economyColor,mywidth/2.5),
buildCard(context,'FDI', '1.45T', '2021 (AED)',economyColor,economyColor,mywidth/2.5),
]),
buildCategoryTitle('International Trade',economyColor),
buildCardRow([
buildCard(context,'Total Trade', '669.9B', 'Jan - Mar 2024 (AED)',economyColor,economyColor,mywidth/2.5),
buildCard(context,'Total Import', '686B', 'Jan - Mar 2024 (AED)',economyColor,economyColor,mywidth/2.5),
]),
buildCardRow([
buildCard(context,'Total Export', '669.9B', 'Jan - Mar 2024 (AED)',economyColor,economyColor,mywidth/2.5),
buildCard(context,'Total ReExport', '686B', 'Jan - Mar 2024 (AED)',economyColor,economyColor,mywidth/2.5),
]),
buildCategoryTitle('Prices',economyColor),
buildCardRow([
buildCard(context,'Total Export', '669.9B', 'Jan - Mar 2024 (AED)',economyColor,economyColor,mywidth/1.2),
]),
],
),
CustomExpandableTile(
title: 'SOCIAL',
titleBackgroundColor: socialColor,
children: [
buildCategoryTitle('Population',socialColor),
buildCardRow([
InkWell(onTap: (){},child: buildCard(context,'Population', '9.89M', '2024',socialColor,socialColor,mywidth/2.5)),
buildCard(context,'Population Growth', '2.1%', '2023',socialColor,socialColor,mywidth/2.5),
]),
buildCategoryTitle('Vital Statistics',socialColor),
buildCardRow([
buildCard(context,'Marriages', '96%', '2023',socialColor,socialColor,mywidth/2.5),
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),
]),
],
),
],
),
);
}
Widget buildCategoryTitle(String title,Color color) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: color,
),
),
);
}
Widget buildCardRow(List<Widget> cards) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: cards.map((card) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 2.0),
child: card,
);
}).toList(),
),
);
}
Widget buildCard(BuildContext context,String title, String value, String subtitle,Color bordercolor,boldColor,double mywidth) {
// double myheight = MediaQuery.of(context).size.height;
// double mywidth = MediaQuery.of(context).size.width;
return Card(
elevation: 2,
child: Container(
width: mywidth,
decoration: BoxDecoration(
color: Colors.white, // Background color
border: Border.all(
color: bordercolor, // Border color
width: 2, // Border width
),
borderRadius: BorderRadius.circular(12), // Optional: Rounded corners
),
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
textAlign: TextAlign.center,
style: robotoRegular11,
),
SizedBox(height: 8),
Text(
subtitle,
textAlign: TextAlign.center,
style: subtitleStyle
),
SizedBox(height: 8),
Text(
value,
style: TextStyle(
fontSize: 26,
color: boldColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
}
}
class CustomExpandableTile extends StatefulWidget {
final String title;
final Color titleBackgroundColor;
final List<Widget> children;
const CustomExpandableTile({
required this.title,
required this.titleBackgroundColor,
required this.children,
});
@override
_CustomExpandableTileState createState() => _CustomExpandableTileState();
}
class _CustomExpandableTileState extends State<CustomExpandableTile> {
bool isExpanded = false;
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
return Card(
elevation: 4,
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
isExpanded = !isExpanded;
});
},
child: Container(
decoration: BoxDecoration(
color: widget.titleBackgroundColor,
borderRadius: BorderRadius.all(Radius.circular(12))
),
padding: const EdgeInsets.all(12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.title,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Icon(
isExpanded
? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down,
color: Colors.white,
),
],
),
),
),
ClipRRect(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
width: double.infinity,
height: isExpanded ? myheight : 0,
child: isExpanded
? SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20))
),
padding: const EdgeInsets.all(10),
child: Column(
children: widget.children,
),
),
)
: null,
),
),
],
),
);
}
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
const Color economyColor = Color(0xFF90B0D5);
const Color socialColor = Color(0xFFAA8E83);
const Color environmentColor = Color(0xFF7DAFBC);
const Color environmentboldColor = Color(0xFF90B0D5);
const TextStyle subtitleStyle = TextStyle(
fontFamily: 'Roboto', // Font family set to Roboto
fontWeight: FontWeight.w400, // Regular weight (w400)
fontSize: 11,
color: Color(0xFF8E8E8E) // Font size 11
);
const TextStyle robotoRegular11 = TextStyle(
fontFamily: 'Roboto', // Font family set to Roboto
fontWeight: FontWeight.w400, // Regular weight (w400)
fontSize: 11,
color: Color(0xFF000000) // Font size 11
);

View File

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

View File

@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:share_plus/share_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
class BaseScaffold extends StatelessWidget {
class BaseScaffold extends StatefulWidget {
final Widget body;
final Widget title;
final List<Widget>? actions;
@ -17,6 +20,81 @@ class BaseScaffold extends StatelessWidget {
this.onBackIconPressed,
}) : super(key: key);
@override
_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['username'] ?? '';
userEmail = userDetailsResponse.data['email'] ?? '';
userAvatar = userDetailsResponse.data['avatar'] ?? '';
role = userDetailsResponse.data['role'] ?? '';
String recordId = userId;
String collectionId =
userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_';
if (userAvatar!.isNotEmpty && recordId.isNotEmpty) {
_avatarUrl =
'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar';
} else {
_avatarUrl = ''; // Reset to default or empty
}
});
} catch (e) {
print('Error fetching user details: $e');
}
}
@override
Widget build(BuildContext context) {
@ -24,30 +102,34 @@ class BaseScaffold extends StatelessWidget {
String currentRoute = GoRouterState.of(context).matchedLocation;
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(title: title,
leading:showBackIcon
? IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.arrow_back_ios_new_sharp),
onPressed: onBackIconPressed ??
() {
Navigator.of(context).pop(); // Default back button behavior
},
) : null,
actions: [
IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
if (showBackIcon)
Builder(
builder: (context) => IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.menu),
onPressed: () {
Scaffold.of(context).openDrawer(); // Opens the drawer
},
),
),
],),
appBar: AppBar(
title: widget.title,
leading:widget.showBackIcon
? IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.arrow_back_ios_new_sharp),
onPressed: widget.onBackIconPressed ??
() {
Navigator.of(context).pop(); // Default back button behavior
},
) : null,
actions: [
// IconButton(
// onPressed: () {
// // Share logic here
// print("Share icon pressed");
// Share.share(
// 'Open the app: fcscapp://home\n\n'
// 'If you dont have the app installed, '
// 'visit: http://localhost:65493');
// },
// icon: Icon(Icons.share),
// ),
IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
],
),
drawer: Drawer(
child: ListView(
children: [
@ -70,18 +152,39 @@ class BaseScaffold extends StatelessWidget {
child: Row(
children: [
SizedBox(
width: mywidth / 8,
child: Image(
image: AssetImage(
'assets/edit_profile/profile.png'))),
width: mywidth / 8,
height: mywidth / 8,
child: ClipOval(
child: _avatarUrl.isNotEmpty
? Image(
image: NetworkImage(_avatarUrl),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
)
: Image(
image: AssetImage(
'assets/edit_profile/profile.png'),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
),
//child: Image(image: AssetImage('assets/edit_profile/profile.png'))
),
SizedBox(
width: mywidth / 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Mohammad'),
Text('Mohammad@fcsc.com')
// Text(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),
],
)
],
@ -90,34 +193,45 @@ class BaseScaffold extends StatelessWidget {
],
),
),
if (role != 'admin')
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/message.png'))),
title: Text('Feedback'),
onTap: () => context.go('/feedback'),
),
if (role == 'admin')
ListTile(
leading: SizedBox(
height: myheight / 15,
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/message.png'))),
title: Text('Feedback'),
onTap: () => context.go('/feedback'),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
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'))),
child:
Image(image: AssetImage('assets/icons/drawer/book.png'))),
title: Text('User Guide'),
onTap: () => context.go('/user-guide'),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/logout.png'))),
title: Text('Logout'),
onTap: () => context.go('/'),
),
],
),
),
@ -162,14 +276,14 @@ class BaseScaffold extends StatelessWidget {
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
),
body: body,
body: widget.body,
);
}
//Map the current route to the selected index
// Map the current route to the selected index
int _getSelectedIndex(String route) {
switch (route) {
case '/':
case '/myhomepage':
return 0;
case '/about':
return 1;
@ -186,7 +300,7 @@ class BaseScaffold extends StatelessWidget {
void _onItemTapped(BuildContext context, int index) {
switch (index) {
case 0:
context.go('/');
context.go('/myhomepage');
break;
case 1:
context.go('/about');

View File

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