Marrages card Implemented
This commit is contained in:
commit
94ef1e8bf3
@ -26,8 +26,8 @@ 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_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
|
||||
@ -294,19 +294,23 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/Competitiveness/competitiveness.dart';
|
||||
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/Country_Profile/country_profile.dart';
|
||||
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/UAE_Numbers/Social/marriages.dart';
|
||||
import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/UAE_Numbers/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';
|
||||
|
||||
import 'package:uae_stat/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart';
|
||||
import 'package:uae_stat/presentation/Screens/Bottom Navigation Pages/Competitiveness/competitiveness.dart';
|
||||
import 'package:uae_stat/presentation/Screens/Bottom Navigation Pages/Country_Profile/country_profile.dart';
|
||||
|
||||
import '../domain/use_cases/preferences_use_case.dart';
|
||||
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';
|
||||
@ -322,7 +326,12 @@ final GoRouter router = GoRouter(
|
||||
GoRoute(
|
||||
path: '/',
|
||||
//builder: (context, state) => LoginRoute(),
|
||||
builder: (context, state) => MyHomePage(),
|
||||
builder: (context, state) => MyHomePage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/login',
|
||||
builder: (context, state) => LoginRoute(),
|
||||
//builder: (context, state) => LoginRoute(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/myhomepage',
|
||||
@ -332,6 +341,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(
|
||||
@ -382,24 +407,30 @@ final GoRouter router = GoRouter(
|
||||
path: '/user-guide',
|
||||
builder: (context, state) => UserGuide(),
|
||||
routes: <RouteBase>[
|
||||
GoRoute(
|
||||
path: '/features',
|
||||
name: 'features',
|
||||
builder: (context, state) => UsingFeatures(),
|
||||
GoRoute(path: '/features',
|
||||
name: 'features',
|
||||
builder: (context, state) => UsingFeatures(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/faq',
|
||||
name: 'faq',
|
||||
builder: (context, state) => FAQPage(),
|
||||
|
||||
GoRoute(path: '/faq',
|
||||
name: 'faq',
|
||||
builder: (context, state) => FAQPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/gettingStarted',
|
||||
name: 'gettingStarted',
|
||||
builder: (context, state) => GettingStarted(),
|
||||
|
||||
GoRoute(path: '/gettingStarted',
|
||||
name: 'gettingStarted',
|
||||
builder: (context, state) => GettingStarted(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// GoRoute(
|
||||
// path: '/manageuser',
|
||||
// builder: (context, state) {
|
||||
// // Retrieve the title from extra or query params
|
||||
// final title = state.extra as String? ?? 'Manage users';
|
||||
// return ManageUserRouter(title: title);
|
||||
// },
|
||||
// ),
|
||||
GoRoute(
|
||||
path: '/editProfile',
|
||||
builder: (context, state) => EditProfile(),
|
||||
@ -409,12 +440,14 @@ final GoRouter router = GoRouter(
|
||||
builder: (context, state) => ManageUserRouter(),
|
||||
),
|
||||
|
||||
|
||||
|
||||
// Bottom Navigation Routes
|
||||
// GoRoute(
|
||||
// path: '/uaenumbers',
|
||||
// builder: (context, state) => UaeNumbers(),
|
||||
// ),
|
||||
GoRoute(
|
||||
path: '/uaenumbers',
|
||||
builder: (context, state) => UaeNumbers(),
|
||||
path: '/uaenumbers',
|
||||
builder: (context,state) => UaeNumbers()
|
||||
),
|
||||
|
||||
GoRoute(
|
||||
@ -427,8 +460,6 @@ final GoRouter router = GoRouter(
|
||||
builder: (context, state) => CountryProfile(),
|
||||
),
|
||||
|
||||
|
||||
// UAE NUMBER Routes
|
||||
GoRoute(
|
||||
path: '/marriages',
|
||||
builder: (context, state) => Marriages(),
|
||||
|
||||
@ -14,7 +14,6 @@ class Marriages extends StatelessWidget {
|
||||
final List<String> xAxisData = ['2019', '2020', '2021', '2022', '2023'];
|
||||
final List<double> yAxisData = [2, 4, 1, 5, 3];
|
||||
return BaseScaffold(
|
||||
//appbarActions: IconButton(onPressed: (){}, icon: Icon(Icons.arrow_back_ios_new)),
|
||||
appbarColor: Color(0xFFC6BEB2),
|
||||
title: Text("UAE Numbers",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),),
|
||||
showBackButton: true,
|
||||
@ -92,7 +91,7 @@ class Marriages extends StatelessWidget {
|
||||
),
|
||||
SizedBox(height: myheight/20,),
|
||||
Container(
|
||||
height: myheight/2,
|
||||
height: myheight/2.5,
|
||||
width: mywidth/1.2,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
|
||||
1225
lib/presentation/Screens/charts/chart.dart
Normal file
1225
lib/presentation/Screens/charts/chart.dart
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
|
||||
328
lib/presentation/Screens/demo_home2.dart
Normal file
328
lib/presentation/Screens/demo_home2.dart
Normal 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,
|
||||
});
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -1,64 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomContainer extends StatelessWidget {
|
||||
final String text;
|
||||
final EdgeInsetsGeometry padding;
|
||||
final bool isBulletPoint;
|
||||
final TextStyle? textStyle;
|
||||
final double? fontSize;
|
||||
final double? height;
|
||||
final double defaultFontSize ;
|
||||
final TextDecoration textDecoration ;
|
||||
final Color? decorationColor;
|
||||
final FontWeight fontWeight;
|
||||
final Color color;
|
||||
class CustomTextRich extends StatelessWidget {
|
||||
|
||||
const CustomContainer({
|
||||
const CustomTextRich({
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.textSpans,
|
||||
this.padding = const EdgeInsets.all(8.0),
|
||||
this.isBulletPoint = false,
|
||||
this.textStyle,
|
||||
this.fontSize,
|
||||
this.defaultFontSize=14,
|
||||
this.height,
|
||||
this.textDecoration = TextDecoration.none,
|
||||
this.fontWeight =FontWeight.w500,
|
||||
this.decorationColor,
|
||||
this.color=const Color(0xFF898C81),
|
||||
this.textAlign = TextAlign.left,
|
||||
});
|
||||
|
||||
final List<TextSpan> textSpans;
|
||||
final EdgeInsetsGeometry padding;
|
||||
final TextAlign textAlign;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (isBulletPoint)
|
||||
Text(
|
||||
"• ",
|
||||
return SingleChildScrollView(
|
||||
child :Padding(
|
||||
padding: padding,
|
||||
child: Text.rich(
|
||||
TextSpan(children: textSpans),
|
||||
textAlign: textAlign,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
style: TextStyle(fontSize: fontSize ?? defaultFontSize,
|
||||
color: color,
|
||||
fontWeight: fontWeight,
|
||||
height: height,),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? defaultFontSize,
|
||||
color: color,
|
||||
fontWeight: fontWeight,
|
||||
height: height,
|
||||
decoration: textDecoration,
|
||||
decorationColor: decorationColor ?? color,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
}
|
||||
|
||||
static TextSpan createTextSpan(
|
||||
String text, {
|
||||
double? fontSize,
|
||||
Color color = const Color(0xFF898C81),
|
||||
FontWeight fontWeight = FontWeight.w500,
|
||||
double? height,
|
||||
double defaultFontSize = 14,
|
||||
TextDecoration textDecoration = TextDecoration.none,
|
||||
Color? decorationColor,
|
||||
double spacingTop = 0.0,
|
||||
double spacingBottom = 0.0,
|
||||
}) {
|
||||
String spacedText = (spacingTop > 0.0 || spacingBottom > 0.0)
|
||||
? '${'\n' * spacingTop.toInt()}$text${'\n' * spacingBottom.toInt()}'
|
||||
: text;
|
||||
return TextSpan(
|
||||
text: spacedText,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ?? defaultFontSize,
|
||||
color: color,
|
||||
fontWeight: fontWeight,
|
||||
height: height,
|
||||
decoration: textDecoration,
|
||||
decorationColor: decorationColor ?? color,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../custom_drawer_routes.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
|
||||
|
||||
class FAQPage extends StatefulWidget {
|
||||
const FAQPage({super.key});
|
||||
@ -13,38 +13,63 @@ class _FAQPageState extends State<FAQPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseScaffold(
|
||||
title: Text('FAQs'),
|
||||
body: Scrollbar(
|
||||
thumbVisibility: true,
|
||||
thickness: 6,
|
||||
radius: Radius.circular(10),
|
||||
interactive: true,
|
||||
child:SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
title: Text('FAQs',
|
||||
style: TextStyle(
|
||||
color:Color(0xFF7296BE),
|
||||
fontWeight: FontWeight.w500,
|
||||
),),
|
||||
showBackButton: true,
|
||||
body: SafeArea(child:Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
text: 'Here are some common questions about the ',
|
||||
style: TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey,
|
||||
),
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Text(
|
||||
'HERE ARE SOME COMMON QUESTIONS ABOUT THE FEDERAL COMPETITIVENESS AND STATISTICS CENTRE (FCSC) MOBILE APPLICATION:',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF265E84), // Text color
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600
|
||||
),
|
||||
TextSpan(
|
||||
text:' Federal Competitiveness and Statistics Centre (FCSC),',
|
||||
style: TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'mobile application:',
|
||||
style: TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
color: Colors.grey,
|
||||
child: QuestionAnswerScrollView()
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(child: Scrollbar(
|
||||
thumbVisibility: true,
|
||||
thickness: 8,
|
||||
radius: Radius.circular(10),
|
||||
interactive: true,
|
||||
child:SingleChildScrollView(
|
||||
child:Container(
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
color: Colors.grey[50],
|
||||
child: QuestionAnswerScrollView(),
|
||||
),
|
||||
),
|
||||
),),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -52,24 +77,194 @@ class _FAQPageState extends State<FAQPage> {
|
||||
|
||||
}
|
||||
class QuestionAnswerScrollView extends StatelessWidget {
|
||||
final List<Map<String, String>> questionsAndAnswers = [
|
||||
{'question': '1. What is the purpose of this app?', 'answer': 'The app provides official UAE statistics across categories like Economy, Environment, and Social. It allows users to explore datasets, view trends, and access detailed metrics to make informed decisions.'},
|
||||
{'question': '2. How do I bookmark a metric?',
|
||||
'answer': 'When viewing a metric, tap on the Bookmark icon. Your bookmarks are accessible from the My Bookmarks section in the navigation bar.'},
|
||||
{'question': '3.Can I view the app in another language?', 'answer': 'Yes, the app supports both English and Arabic. You can toggle the language using the switch in the top-right corner of the app.'},
|
||||
{'question': '4.What happens if I forget my password?','answer':'Tap on the Forgot Password? link on the login page. Follow the steps to reset your password via your registered email address.'},
|
||||
{'question':'5. Can I edit my profile details?','answer': 'Yes, you can edit specific fields such as Date of Birth and User Image. However, certain fields like Username and Email are non-editable for security reasons.'},
|
||||
{'question':'6.How often is the data updated?','answer':'The app updates its datasets regularly to ensure users have access to the latest statistics. Notifications are sent whenever significant updates are made.'},
|
||||
{'question':'7.Do I need to create an account to use the app?',
|
||||
'answer':"Yes, the app is strictly for registered and approved users. To access the data:You need to sign up using the Register Now option on the login screen .Your registration must be approved by the admin.Once approved, you can log in to access the app's features and datasets.Guest access is not available for this application."},
|
||||
{'question':'8.How can I navigate through the app?','answer':'Use the main categories on the homepage (e.g., Economy, Environment) to access subcategories and detailed KPIs.Drill down into specific metrics or graphical views by tapping on a KPI.Access additional features like Bookmarks or Profile through the navigation bar.'},
|
||||
{'question':'9.What types of data are available?','answer':'The app offers data on:Economy: GDP, growth rates, and economic trends.Environment: Electricity production, water consumption, and more.Social: Labor force distribution, participation rates, and demographic data.'},
|
||||
{'question':'10.What types of graphs and charts are available?','answer':'The app provides a variety of visualizations, including:Line charts for trends.Bar and column charts for comparisons.Stacked charts for multi-layered data views.'},
|
||||
];
|
||||
const QuestionAnswerScrollView({super.key});
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Map<String, dynamic>> questionsAndAnswers = [
|
||||
{'question':'What is the purpose of this app?', 'answer': 'The app provides official UAE statistics across categories like Economy, Environment, and Social. It allows users to explore datasets, view trends, and access detailed metrics to make informed decisions.'},
|
||||
{'question':'Do I need to create an account to use the app?', 'answer':RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Yes, the app is strictly for registered and approved users. To access the data:\n\n',
|
||||
style: TextStyle(fontWeight: FontWeight.normal, color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' 1. You need to sign up using the Register Now option on the login screen.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' 2. Your registration must be approved by the admin.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
|
||||
TextSpan(
|
||||
text: " 3. Once approved, you can log in to access the app's features and datasets.\n\nGuest access is not available for this application.\n ",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),},
|
||||
{'question':'How can I navigate through the app?','answer':'• Use the main categories on the homepage (e.g., Economy, Environment) to access subcategories and detailed KPIs.\n• Drill down into specific metrics or graphical views by tapping on a KPI.\n• Access additional features like Bookmarks or Profile through the navigation bar.\n'},
|
||||
{'question':'What types of data are available?', 'answer':RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'The app offers data on:\n\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' • Economy',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' GDP, growth rates, and economic trends\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
|
||||
TextSpan(
|
||||
text: ' • Environment:',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' Electricity production, water consumption, and more.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' • Social:',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' Labor force distribution, participation rates, and demographic data.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),},
|
||||
{'question':'How do I bookmark a metric?', 'answer': RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'When viewing a metric, tap on the',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' Bookmark ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'icon. Your bookmarks are accessible from the',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
|
||||
TextSpan(
|
||||
text: 'My Bookmarks',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'section in the navigation bar.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),},
|
||||
{'question':'Can I view the app in another language?', 'answer': RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Yes, the app supports both ',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'English ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'and',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
|
||||
TextSpan(
|
||||
text: ' Arabic ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: '. You can toggle the language using the switch in the top-right corner of the app.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),},
|
||||
{'question':'What happens if I forget my password?','answer':'Tap on the Forgot Password? link on the login page. Follow the steps to reset your password via your registered email address.\n'},
|
||||
{'question':'Can I edit my profile details?','answer': 'Yes, you can edit specific fields such as Date of Birth and User Image. However, certain fields like Username and Email are non-editable for security reasons.\n'},
|
||||
{'question':'How often is the data updated?','answer':'The app updates its datasets regularly to ensure users have access to the latest statistics. Notifications are sent whenever significant updates are made.\n'},
|
||||
{'question':'What types of graphs and charts are available?','answer':'The app provides a variety of visualizations, including:\n • Line charts for trends.\n • Bar and column charts for comparisons.\n • Stacked charts for multi-layered data views.\n'},
|
||||
{'question':'Can I share the data or charts?','answer':RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Yes, you can share data or charts directly from the app by tapping the ',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'Share ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'button available on most pages.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),},
|
||||
{'question':'What should I do if I encounter an issue?','answer':RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'For technical support or feedback, navigate to the ',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'Help ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'section in the app and contact the support team.\n',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),},
|
||||
{'question':'How do I log out of the app?','answer':RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'Go to the ',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'Profile ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'section and tap the ',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'Logout ',
|
||||
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'option in the top-right corner.\n',
|
||||
style: TextStyle(color: Colors.grey), ),
|
||||
],
|
||||
),
|
||||
),},
|
||||
];
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: questionsAndAnswers.map((qa) => QuestionAnswerCard(qa: qa)).toList(),
|
||||
@ -78,9 +273,10 @@ class QuestionAnswerScrollView extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class QuestionAnswerCard extends StatefulWidget {
|
||||
final Map<String, String> qa;
|
||||
QuestionAnswerCard({required this.qa});
|
||||
class QuestionAnswerCard extends StatefulWidget { // Use dynamic to accommodate RichText
|
||||
|
||||
const QuestionAnswerCard({super.key, required this.qa});
|
||||
final Map<String, dynamic> qa;
|
||||
|
||||
@override
|
||||
_QuestionAnswerCardState createState() => _QuestionAnswerCardState();
|
||||
@ -92,18 +288,18 @@ class _QuestionAnswerCardState extends State<QuestionAnswerCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
color: Colors.grey[50],
|
||||
elevation: 1,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.zero, // No rounding, it's a rectangle
|
||||
),
|
||||
margin: EdgeInsets.symmetric(vertical: 0,),
|
||||
margin: EdgeInsets.symmetric(vertical: 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
textColor:Color(0xFF414042),
|
||||
textColor: Color(0xFF414042),
|
||||
title: Text(
|
||||
widget.qa['question']!,
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
|
||||
@ -118,8 +314,10 @@ class _QuestionAnswerCardState extends State<QuestionAnswerCard> {
|
||||
if (isExpanded)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
widget.qa["answer"]!,
|
||||
child: widget.qa['answer'] is RichText
|
||||
? widget.qa['answer']
|
||||
: Text(
|
||||
widget.qa['answer'] ?? '',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,4 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
@ -5,152 +6,174 @@ import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_g
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
|
||||
|
||||
import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
class GettingStarted extends StatelessWidget {
|
||||
GettingStarted({super.key});
|
||||
|
||||
final String url = 'https://fcsc.gov.ae/en-us/Pages/home.aspx';
|
||||
final fcscBanner = Image.asset(
|
||||
BannerAssetPath.fcsc,
|
||||
height: 56,
|
||||
alignment:Alignment.center,
|
||||
);
|
||||
|
||||
final List<Map<String, dynamic>> contentList = [
|
||||
{
|
||||
'text': 'This app provides a centralized platform to access key statistical data and insights about the UAE, empoweringusers with accurate and up-to-date information on various sectors.',
|
||||
'fontSize': 16.0,
|
||||
'color': Color(0xFF898C81),
|
||||
'fontWeight': FontWeight.normal,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
{
|
||||
'text': 'How to Get Started',
|
||||
'fontSize': 18.0,
|
||||
'color': Color(0xFF414042),
|
||||
'fontWeight': FontWeight.w600,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
{
|
||||
'text': '1.Download the app from the App Store or Google Play Store.',
|
||||
'fontSize': 14.0,
|
||||
'color': Color(0xFF898C81),
|
||||
'fontWeight': FontWeight.normal,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
{
|
||||
'text': '2.Log in to unlock advanced features or continue as a guest.',
|
||||
'fontSize': 14.0,
|
||||
'color': Color(0xFF898C81),
|
||||
'fontWeight': FontWeight.normal,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
{
|
||||
'text': '3.Navigate through categories, explore metrics, and bookmark essential information.',
|
||||
'fontSize': 14.0,
|
||||
'color': Color(0xFF898C81),
|
||||
'fontWeight': FontWeight.normal,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
{
|
||||
'text': 'Stay Updated',
|
||||
'fontSize': 18.0,
|
||||
'color': Color(0xFF414042),
|
||||
'fontWeight': FontWeight.bold,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
{
|
||||
'text': 'The app regularly updates datasets and features to reflect the latest information. Notifications will alert you about new data or improvements.',
|
||||
'fontSize': 14.0,
|
||||
'color': Color(0xFF898C81),
|
||||
'fontWeight': FontWeight.normal,
|
||||
'isBulletPoint': false,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseScaffold(title: Text ('Getting Started'),
|
||||
body: Scrollbar(
|
||||
thumbVisibility: true,
|
||||
thickness: 6,
|
||||
radius: Radius.circular(10),
|
||||
interactive: true,
|
||||
child:SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Text(
|
||||
'WELCOME TO THE FEDERAL COMPETITIVENESS AND STATISTICS CENTRE (FCSC) MOBILE APPLICATION.',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF265E84), // Text color
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
color: Color(0xFFD9D9D9),
|
||||
child:ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: contentList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = contentList[index];
|
||||
return CustomContainer(
|
||||
text: item['text'],
|
||||
fontSize: item['fontSize']?? 20,
|
||||
color: item['color'],
|
||||
fontWeight: item['fontWeight'],
|
||||
height:item['height'],
|
||||
isBulletPoint: item['isBulletPoint'] ?? false,
|
||||
textDecoration: item['textDecoration'] ?? TextDecoration.none,
|
||||
decorationColor: item['decorationColor'],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Color(0xFFD9D9D9),
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'For more information please visit ',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Color(0xFF265E84),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
List<TextSpan> textSpans = [
|
||||
|
||||
TextSpan(
|
||||
text: 'www.fcsc.gov.ae',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Color(0xFF568898),
|
||||
fontWeight: FontWeight.normal,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor:Color(0xFF568898),
|
||||
),
|
||||
),
|
||||
],
|
||||
CustomTextRich.createTextSpan('How to Get Started\n', fontSize: 17,
|
||||
color: Colors.black87,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
CustomTextRich.createTextSpan('1.Download the app from the App Store or Google Play Store.',
|
||||
fontSize: 13, color:Color(0xFF898C81),
|
||||
fontWeight: FontWeight.normal ,
|
||||
spacingTop: 1.9,
|
||||
),
|
||||
CustomTextRich.createTextSpan(
|
||||
'2.Log in to unlock advanced features or continue as a guest.\n',
|
||||
fontSize: 13, color:Color(0xFF898C81),
|
||||
fontWeight: FontWeight.normal ,
|
||||
spacingTop: 1.9,),
|
||||
|
||||
CustomTextRich.createTextSpan(
|
||||
'3.Navigate through categories, explore metrics, and bookmark essential information.\n',
|
||||
fontSize: 13, color:Color(0xFF898C81),
|
||||
fontWeight: FontWeight.normal ,
|
||||
),
|
||||
|
||||
CustomTextRich.createTextSpan('\nStay Updated', fontSize: 15,
|
||||
color: Colors.black87,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 2,
|
||||
),
|
||||
|
||||
CustomTextRich.createTextSpan(
|
||||
'\nThe app regularly updates datasets and features to reflect the latest information. Notifications will alert you about new data or improvements.',
|
||||
fontSize: 13, color:Color(0xFF898C81),
|
||||
fontWeight: FontWeight.normal ,
|
||||
),
|
||||
|
||||
CustomTextRich.createTextSpan(
|
||||
'Support decision-making and research with reliable, up-to-date data.\n \n ',
|
||||
fontSize: 14.0,
|
||||
color: Color(0xFF898C81),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
|
||||
|
||||
];
|
||||
return BaseScaffold( title: Text('About the App',
|
||||
style: TextStyle(
|
||||
color:Color(0xFF265E84),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
showBackButton: true,
|
||||
body:SafeArea(child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
text: 'The',
|
||||
style: TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text:' Federal Competitiveness and Statistics Centre (FCSC),',
|
||||
style: TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Color(0xFFD9D9D9),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Center( child: fcscBanner,),
|
||||
TextSpan(
|
||||
text:' in your App is designed to provide registered and approved users with access to accurate and comprehensive statistics about the UAE. The app serves as a centralized platform for exploring key datasets, trends, and insights across various sectors.',
|
||||
style: TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(child: Scrollbar(
|
||||
thumbVisibility: true,
|
||||
thickness: 6,
|
||||
radius: Radius.circular(10),
|
||||
interactive: true,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
color: Colors.grey[50], // Set the background color here
|
||||
// child: SingleChildScrollView(
|
||||
child: CustomTextRich(
|
||||
textSpans: textSpans,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Colors.grey[50],
|
||||
padding: EdgeInsets.only(bottom: 26.0),
|
||||
child:Text.rich(
|
||||
TextSpan(
|
||||
text: 'For more information please visit ',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Color(0xFF265E84),
|
||||
fontWeight: FontWeight.normal,),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'www.fcsc.gov.ae',
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
color: Color(0xFF568898),
|
||||
fontWeight: FontWeight.normal,
|
||||
decoration: TextDecoration.underline,
|
||||
decorationColor:Color(0xFF568898),
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
final Uri uri = Uri.parse(url);
|
||||
if (await launchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Colors.grey[50],
|
||||
padding: EdgeInsets.only(bottom: 26.0),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Center(
|
||||
child: fcscBanner,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
),),
|
||||
],
|
||||
), ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,14 +43,10 @@ class _UserGuideState extends State<UserGuide> {
|
||||
// Each pair defines a row of (Color, Text) pairs
|
||||
[
|
||||
{'routePath':'gettingStarted','color': Color(0xFF90B0D5), 'text': 'Getting Started', 'icon': 'START', 'index': '1'},
|
||||
{'routePath':'features','color': Color(0xFF497B8C), 'text': 'Account & Profile', 'icon': Icons.person_outline_rounded, 'index': '2'},
|
||||
{'routePath':'features','color': Color(0xFFAA8E83), 'text': 'Using Features', 'icon': Icons.stars_outlined, 'index': '2'},
|
||||
],
|
||||
[
|
||||
{'routePath':'features','color': Color(0xFFAA8E83), 'text': 'Using Features', 'icon': Icons.stars_outlined, 'index': '3'},
|
||||
{'routePath':'features','color': Color(0xFF265E84), 'text': 'Contact', 'icon': Icons.local_phone_outlined, 'index': '4'},
|
||||
],
|
||||
[
|
||||
{'routePath':'faq','color': Color(0xFF7296BE), 'text': 'FAQs', 'icon': Icons.question_answer_sharp, 'index': '5'},
|
||||
{'routePath':'faq','color': Color(0xFF7296BE), 'text': 'FAQs', 'icon': Icons.question_answer_sharp, 'index': '3'},
|
||||
// {'routePath':'features','color': Color(0xFF7DAFBC), 'text': 'Advanced Settings', 'icon': Icons.settings_outlined, 'index': '6'},
|
||||
],
|
||||
]),
|
||||
|
||||
@ -1,203 +1,11 @@
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:go_router/go_router.dart';
|
||||
//
|
||||
// class BaseScaffold extends StatelessWidget {
|
||||
// final Widget body;
|
||||
// final Widget title;
|
||||
// final Widget? appbarActions;
|
||||
// final List<Widget>? actions;
|
||||
// final Color? appbarColor,mytitleColor;
|
||||
//
|
||||
// const BaseScaffold({
|
||||
// Key? key,
|
||||
// required this.body,
|
||||
// required this.title,
|
||||
// this.actions,
|
||||
// this.appbarColor,
|
||||
// this.mytitleColor,
|
||||
// this.appbarActions
|
||||
// }) : super(key: key);
|
||||
// // final Widget body;
|
||||
// //
|
||||
// // const BaseScaffold({required this.body});
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// // Get the current route to highlight the active item
|
||||
// String currentRoute = GoRouterState.of(context).matchedLocation;
|
||||
// double myheight = MediaQuery.of(context).size.height;
|
||||
// double mywidth = MediaQuery.of(context).size.width;
|
||||
// return Scaffold(
|
||||
// appBar: AppBar(title: title,backgroundColor: appbarColor, actions: [
|
||||
// IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
|
||||
// ],
|
||||
// leading: appbarActions,
|
||||
//
|
||||
// ),
|
||||
//
|
||||
// drawer: Drawer(
|
||||
// child: ListView(
|
||||
// children: [
|
||||
// DrawerHeader(
|
||||
// //decoration: BoxDecoration(color: Colors.blue),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
// children: [
|
||||
// Row(
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// width: mywidth / 8,
|
||||
// child: Image(
|
||||
// image: AssetImage('assets/logos/fcsc.png'))),
|
||||
// ],
|
||||
// ),
|
||||
// Divider(),
|
||||
// InkWell(
|
||||
// onTap: () => context.go('/editProfile'),
|
||||
// child: Row(
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// width: mywidth / 8,
|
||||
// child: Image(
|
||||
// image: AssetImage(
|
||||
// 'assets/edit_profile/profile.png'))),
|
||||
// SizedBox(
|
||||
// width: mywidth / 20,
|
||||
// ),
|
||||
// Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text('Mohammad'),
|
||||
// Text('Mohammad@fcsc.com')
|
||||
// ],
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// 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'))),
|
||||
// title: Text('User Guide'),
|
||||
// onTap: () => context.go('/user-guide'),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// bottomNavigationBar: BottomNavigationBar(
|
||||
// currentIndex: _getSelectedIndex(currentRoute),
|
||||
// onTap: (index) => _onItemTapped(context, index),
|
||||
// type: BottomNavigationBarType.fixed,
|
||||
// items: [
|
||||
// BottomNavigationBarItem(
|
||||
// icon: SizedBox(
|
||||
// height: myheight / 15,
|
||||
// width: mywidth / 15,
|
||||
// child: Image(
|
||||
// image: AssetImage('assets/icons/bottom_bar/home.png'))),
|
||||
// label: 'Home',
|
||||
// ),
|
||||
// BottomNavigationBarItem(
|
||||
// icon: SizedBox(
|
||||
// height: myheight / 15,
|
||||
// width: mywidth / 15,
|
||||
// child: Image(
|
||||
// image: AssetImage('assets/icons/bottom_bar/uae_map.png'))),
|
||||
// label: 'UAE Numbers',
|
||||
// ),
|
||||
// BottomNavigationBarItem(
|
||||
// icon: SizedBox(
|
||||
// height: myheight / 15,
|
||||
// width: mywidth / 15,
|
||||
// child: Image(
|
||||
// image:
|
||||
// AssetImage('assets/icons/bottom_bar/ranking.png'))),
|
||||
// label: 'Competitiveness'),
|
||||
// BottomNavigationBarItem(
|
||||
// icon: SizedBox(
|
||||
// height: myheight / 15,
|
||||
// width: mywidth / 15,
|
||||
// child: Image(
|
||||
// image: AssetImage('assets/icons/bottom_bar/globe.png'))),
|
||||
// label: 'Country Profile'),
|
||||
// ],
|
||||
// selectedItemColor: Colors.black,
|
||||
// unselectedItemColor: Colors.grey,
|
||||
// showUnselectedLabels: true,
|
||||
// ),
|
||||
// body: body,
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// //Map the current route to the selected index
|
||||
// int _getSelectedIndex(String route) {
|
||||
// switch (route) {
|
||||
// case '/':
|
||||
// return 0;
|
||||
// case '/uaenumbers':
|
||||
// return 1;
|
||||
// case '/competitiveness':
|
||||
// return 2;
|
||||
// case '/countryprofile':
|
||||
// return 3;
|
||||
// default:
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //Handle navigation when an item is tapped
|
||||
// void _onItemTapped(BuildContext context, int index) {
|
||||
// switch (index) {
|
||||
// case 0:
|
||||
// context.go('/');
|
||||
// break;
|
||||
// case 1:
|
||||
// context.go('/uaenumbers');
|
||||
// break;
|
||||
// case 2:
|
||||
// context.go('/competitiveness');
|
||||
// break;
|
||||
// case 3:
|
||||
// context.go('/countryprofile');
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class BaseScaffold extends StatelessWidget {
|
||||
final Widget body;
|
||||
final Widget title;
|
||||
final bool? mycenterTitle;
|
||||
final bool showBackButton;
|
||||
final bool ? showBackButton;
|
||||
final bool ? mycenterTitle;
|
||||
final List<Widget>? actions;
|
||||
final Color? appbarColor, mytitleColor;
|
||||
|
||||
@ -206,10 +14,12 @@ class BaseScaffold extends StatelessWidget {
|
||||
required this.body,
|
||||
required this.title,
|
||||
this.actions,
|
||||
this.appbarColor,
|
||||
this.mytitleColor,
|
||||
this.showBackButton = false, this.mycenterTitle = false, // Default is to show the drawer icon
|
||||
this.showBackButton = false,
|
||||
this.mycenterTitle = false, this.appbarColor, this.mytitleColor
|
||||
}) : super(key: key);
|
||||
// final Widget body;
|
||||
//
|
||||
// const BaseScaffold({required this.body});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -218,19 +28,45 @@ class BaseScaffold extends StatelessWidget {
|
||||
double myheight = MediaQuery.of(context).size.height;
|
||||
double mywidth = MediaQuery.of(context).size.width;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: mycenterTitle,
|
||||
title: title,
|
||||
backgroundColor: appbarColor,
|
||||
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(
|
||||
children: [
|
||||
|
||||
// Show the back button if showBackButton is true, otherwise show the drawer menu
|
||||
if (showBackButton)
|
||||
// Show the back button if showBackButton is true
|
||||
if (showBackButton == true)
|
||||
Positioned(
|
||||
left: 20,
|
||||
left: 15,
|
||||
child: IconButton(
|
||||
color: Colors.white,
|
||||
icon: Icon(Icons.arrow_back_ios_new),
|
||||
@ -245,7 +81,7 @@ class BaseScaffold extends StatelessWidget {
|
||||
child: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return IconButton(
|
||||
color: showBackButton ? Colors.white : Colors.black,
|
||||
color: (showBackButton == true) ? Colors.white : Colors.black,
|
||||
icon: Icon(Icons.menu),
|
||||
onPressed: () {
|
||||
// Open the drawer using the Scaffold context
|
||||
@ -256,67 +92,76 @@ class BaseScaffold extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
actions: actions,
|
||||
),
|
||||
drawer: Drawer(
|
||||
child: ListView(
|
||||
children: [
|
||||
DrawerHeader(
|
||||
child: Container(
|
||||
//decoration: BoxDecoration(color: Colors.blue),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: mywidth/5,
|
||||
height: myheight/15,
|
||||
child: Image.asset('assets/logos/fcsc.png')),
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: mywidth / 8,
|
||||
child: Image(
|
||||
image: AssetImage('assets/logos/fcsc.png'))),
|
||||
],
|
||||
),
|
||||
Divider(),
|
||||
SizedBox(
|
||||
height: myheight/15,
|
||||
InkWell(
|
||||
onTap: () => context.go('/editProfile'),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min, // Ensures the row only takes up as much space as its children need
|
||||
children: [
|
||||
// The profile image with fixed size
|
||||
Image.asset(
|
||||
'assets/edit_profile/profile.png',
|
||||
height: myheight / 10, // This ensures the image fits within the container's height
|
||||
width: myheight / 10, // You can adjust the size as needed
|
||||
),
|
||||
|
||||
// Wrapping the Column in Flexible to ensure no overflow
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Mohammad'),
|
||||
Text('Mohammad@fcsc.com'),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: mywidth / 8,
|
||||
child: Image(
|
||||
image: AssetImage(
|
||||
'assets/edit_profile/profile.png'))),
|
||||
SizedBox(
|
||||
width: mywidth / 20,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Mohammad'),
|
||||
Text('Mohammad@fcsc.com')
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
||||
),),
|
||||
|
||||
),
|
||||
),
|
||||
SizedBox(height: myheight/60,),
|
||||
ListTile(
|
||||
leading: Icon(Icons.feedback),
|
||||
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: Icon(Icons.people),
|
||||
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: Icon(Icons.book),
|
||||
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'),
|
||||
),
|
||||
@ -350,7 +195,7 @@ class BaseScaffold extends StatelessWidget {
|
||||
width: mywidth / 15,
|
||||
child: Image(
|
||||
image:
|
||||
AssetImage('assets/icons/bottom_bar/ranking.png'))),
|
||||
AssetImage('assets/icons/bottom_bar/ranking.png'))),
|
||||
label: 'Competitiveness'),
|
||||
BottomNavigationBarItem(
|
||||
icon: SizedBox(
|
||||
@ -367,6 +212,7 @@ class BaseScaffold extends StatelessWidget {
|
||||
body: body,
|
||||
);
|
||||
}
|
||||
|
||||
//Map the current route to the selected index
|
||||
int _getSelectedIndex(String route) {
|
||||
switch (route) {
|
||||
@ -401,5 +247,3 @@ class BaseScaffold extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import flutter_secure_storage_macos
|
||||
import path_provider_foundation
|
||||
import share_plus
|
||||
import shared_preferences_foundation
|
||||
import url_launcher_macos
|
||||
import video_player_avfoundation
|
||||
import webview_flutter_wkwebview
|
||||
|
||||
@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
||||
FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin"))
|
||||
}
|
||||
|
||||
124
pubspec.lock
124
pubspec.lock
@ -74,50 +74,50 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||
sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "2.4.2"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.1.2"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
|
||||
sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
version: "4.0.3"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||
sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
version: "2.4.3"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
|
||||
sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.13"
|
||||
version: "2.4.14"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
|
||||
sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.2"
|
||||
version: "8.0.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -435,10 +435,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_native_splash
|
||||
sha256: "1152ab0067ca5a2ebeb862fe0a762057202cceb22b7e62692dcbabf6483891bb"
|
||||
sha256: "7062602e0dbd29141fb8eb19220b5871ca650be5197ab9c1f193a28b17537bc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
version: "2.4.4"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -467,26 +467,26 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_secure_storage
|
||||
sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0"
|
||||
sha256: "1913841ac4c7bf57cd2e05b717e1fbff7841b542962feff827b16525a781b3e4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.2.2"
|
||||
version: "9.2.3"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_linux
|
||||
sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b"
|
||||
sha256: bf7404619d7ab5c0a1151d7c4e802edad8f33535abfbeff2f9e1fe1274e2d705
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.2.2"
|
||||
flutter_secure_storage_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_macos
|
||||
sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81"
|
||||
sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "3.1.3"
|
||||
flutter_secure_storage_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -573,10 +573,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: go_router
|
||||
sha256: "2fd11229f59e23e967b0775df8d5948a519cd7e1e8b6e849729e010587b46539"
|
||||
sha256: "7c2d40b59890a929824f30d442e810116caf5088482629c894b9e4478c67472d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.6.2"
|
||||
version: "14.6.3"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -629,10 +629,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
version: "4.1.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -669,10 +669,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_ios
|
||||
sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b"
|
||||
sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.12+1"
|
||||
version: "0.8.12+2"
|
||||
image_picker_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -693,10 +693,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_platform_interface
|
||||
sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80"
|
||||
sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.10.0"
|
||||
version: "2.10.1"
|
||||
image_picker_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -797,10 +797,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
version: "5.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1005,10 +1005,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0"
|
||||
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.5.0"
|
||||
recase:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1100,10 +1100,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "3c7e73920c694a436afaf65ab60ce3453d91f84208d761fbd83fc21182134d93"
|
||||
sha256: a752ce92ea7540fc35a0d19722816e04d0e72828a4200e83a98cf1a1eb524c9a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.4"
|
||||
version: "2.3.5"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1156,10 +1156,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
version: "1.4.2"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1264,10 +1264,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: syncfusion_flutter_core
|
||||
sha256: b1071c698b502e7d55f91352a8b82d42f49f4c96e523d43b6fade5d5af710048
|
||||
sha256: "12735505d616320aebe39a6fc90b6608a09116378d66aee9636b0eddf7b75971"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "28.1.33"
|
||||
version: "28.1.38"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1316,6 +1316,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.1"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.14"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1324,6 +1348,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1376,10 +1408,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898"
|
||||
sha256: "7018dbcb395e2bca0b9a898e73989e67c0c4a5db269528e1b036ca38bcca0d0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.16"
|
||||
version: "2.7.17"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1472,18 +1504,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: b7e92f129482460951d96ef9a46b49db34bd2e1621685de26e9eaafd9674e7eb
|
||||
sha256: "4adc14ea9a770cc9e2c8f1ac734536bd40e82615bd0fa6b94be10982de656cc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.16.3"
|
||||
version: "3.17.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69"
|
||||
sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.9.0"
|
||||
version: "5.10.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1509,5 +1541,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.5.2 <4.0.0"
|
||||
flutter: ">=3.24.0"
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
|
||||
@ -20,8 +20,11 @@ dependencies:
|
||||
injectable: ^2.3.2
|
||||
riverpod_annotation: ^2.3.3
|
||||
cupertino_icons: ^1.0.6
|
||||
|
||||
fl_chart: ^0.70.1
|
||||
|
||||
marquee: ^2.2.3
|
||||
url_launcher: ^6.3.1
|
||||
# dynamic_layouts:
|
||||
# git:
|
||||
# url: https://github.com/flutter/packages.git
|
||||
|
||||
Loading…
Reference in New Issue
Block a user