back button handle added and session

This commit is contained in:
venbaittech 2025-02-08 17:04:27 +05:30
parent 0d4c3cf02e
commit e0fd4267f2
18 changed files with 1519 additions and 1204 deletions

View File

@ -295,6 +295,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:uae_stat/config/sessionCheckScreen.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/Social/marriages.dart';
import 'package:uae_stat/presentation/Screens/auth_verification/registration.dart'; import 'package:uae_stat/presentation/Screens/auth_verification/registration.dart';
import 'package:uae_stat/presentation/Screens/charts/chart.dart'; import 'package:uae_stat/presentation/Screens/charts/chart.dart';
@ -336,34 +337,35 @@ import '../presentation/routes/drawer_routes/Drawer Items/manage_users.dart';
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
Future<String?> _checkSession() async { // Future<String?> _checkSession() async {
print('_checkSession'); // print('_checkSession');
await Future.delayed(Duration(seconds: 2)); // Optional splash effect // await Future.delayed(Duration(seconds: 2)); // Optional splash effect
//
String? sessionToken = // String? sessionToken =
await _secureStorage.read(key: "FlutterSecureStorage.session"); // await _secureStorage.read(key: "FlutterSecureStorage.session");
print('sessionToken $sessionToken'); // print('sessionToken $sessionToken');
//
if (sessionToken != null && sessionToken.isNotEmpty) { // if (sessionToken != null && sessionToken.isNotEmpty) {
print('_checkSession home'); // print('_checkSession home');
return "/myhomepage"; // Redirect to home page if session is valid // return "/myhomepage"; // Redirect to home page if session is valid
} else { // } else {
print('_checkSession login'); // print('_checkSession login');
return "/login"; // Redirect to login page if session is invalid // return "/login"; // Redirect to login page if session is invalid
} // }
} // }
final GoRouter router = GoRouter( final GoRouter router = GoRouter(
initialLocation: '/',
routes: [ routes: [
// GoRoute(
// path: '/',
// //builder: (context, state) => LoginRoute(),
// builder: (context, state) => LoginRoute(),
// ),
GoRoute( GoRoute(
path: '/', path: '/',
redirect: (context, state) async => await _checkSession(), //builder: (context, state) => LoginRoute(),
builder: (context, state) => SessionCheckScreen(),
), ),
// GoRoute(
// path: '/',
// redirect: (context, state) async => await _checkSession(),
// ),
GoRoute( GoRoute(
path: '/internetcheck', path: '/internetcheck',
builder: (context, state) => InternetCheck(), builder: (context, state) => InternetCheck(),

View File

@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:uae_stat/infrastructure/data/p_auth_repo.dart';
class SessionCheckScreen extends StatefulWidget {
@override
_SessionCheckScreenState createState() => _SessionCheckScreenState();
}
class _SessionCheckScreenState extends State<SessionCheckScreen> {
final PAuthRepo _authRepo = PAuthRepo();
@override
void initState() {
super.initState();
_checkSession();
}
Future<void> _checkSession() async {
await Future.delayed(Duration(seconds: 2)); // Optional splash delay
print('fetchLocallyStored');
final session = await _authRepo.fetchLocallyStored();
print('fetchLocallyStored $session');
if (session != null) {
print('myhomepage');
if (mounted) context.go('/myhomepage'); // Redirect to home
} else {
print('login');
if (mounted) context.go('/login'); // Redirect to login
}
}
@override
Widget build(BuildContext context) {
return SizedBox.shrink();
}
}

View File

@ -69,7 +69,7 @@
"password_match": "كلمات المرور غير متطابقة", "password_match": "كلمات المرور غير متطابقة",
"only8charac": "يجب أن تتكون كلمة المرور من 8 أحرف على الأقل", "only8charac": "يجب أن تتكون كلمة المرور من 8 أحرف على الأقل",
"manage_user": "إدارة المستخدمين", "manage_user": "إدارة المستخدم",
"user_name": "اسم المستخدم", "user_name": "اسم المستخدم",
"reg_date": "تاريخ التسجيل", "reg_date": "تاريخ التسجيل",
"status": "الحالة", "status": "الحالة",

View File

@ -71,7 +71,7 @@
"password_match": "Passwords do not match", "password_match": "Passwords do not match",
"only8charac": "Password must be at least 8characters", "only8charac": "Password must be at least 8characters",
"manage_user": "Manage user", "manage_user": "Manage User",
"user_name": "User Name", "user_name": "User Name",
"reg_date": "Registration Date", "reg_date": "Registration Date",
"status": "Status", "status": "Status",

View File

@ -10,9 +10,10 @@ class Competitiveness extends StatelessWidget {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
title: Center( title: Center(

View File

@ -11,9 +11,10 @@ class CountryProfile extends StatelessWidget {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
title: Center( title: Center(

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart'; import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
@ -31,12 +32,16 @@ class UaeNumbers extends StatelessWidget {
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
title: Text("UAE Numbers"), title: Text(context.translate(
'UAE Numbers',
'أرقام الإمارات',
)),
body: uaenumberWidget(), body: uaenumberWidget(),
), ),
); );
@ -107,9 +112,9 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search", hintText: "Search",
prefixIcon: Image.asset( prefixIcon: Image.asset(
MiscIconAssetPath.search, MiscIconAssetPath.search,
width: 20, width: 20,
height: 20, height: 20,
), ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: contentPadding:
@ -389,9 +394,9 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
? SingleChildScrollView( ? SingleChildScrollView(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
// borderRadius: BorderRadius.all(Radius.circular(20)) // borderRadius: BorderRadius.all(Radius.circular(20))
), ),
padding: const EdgeInsets.all(1), padding: const EdgeInsets.all(1),
child: Column( child: Column(
children: widget.children, children: widget.children,

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,9 @@ import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/infrastructure/data/p_auth_repo.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart';
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart'; import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -336,12 +338,62 @@ class _ProfileScreenState extends State<ProfileScreen> {
}); });
} }
final PAuthRepo _authRepo = PAuthRepo();
Future<void> logout(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
await _authRepo.logout();
prefs.clear();
context.go('/login'); // Redirect to login after logout
}
void _showExitConfirmation(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
context.translate(
'Logout',
'تسجيل الخروج',
),
),
content: Text(
context.translate(
'Are you sure you want to logout?',
'هل أنت متأكد أنك تريد تسجيل الخروج؟',
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(), // Close dialog
child: Text(
context.translate(
'Cancel',
'إلغاء',
),
),
),
TextButton(
onPressed: () => logout(context), // Exit the app
child: Text(
context.translate(
'Logout',
'تسجيل الخروج',
),
),
),
],
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/'); _showExitConfirmation(context); // Show exit confirmation dialog
}, },
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
@ -632,7 +684,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}, },
side: BorderSide( side: BorderSide(
color: color:
showError ? Color(0xFFb22222) : Color(0xFF7296BE), showError ? Color(0xFFb22222) : Color(0xFF7296BE),
width: 1, width: 1,
), ),
), ),
@ -646,16 +698,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
Text.rich( Text.rich(
TextSpan( TextSpan(
text: AppLocalizations.of( text: AppLocalizations.of(context)!.agree,
context)! style: TextStyle(color: Color(0xFF898C81)),
.agree,
style: TextStyle(color: Color(0xFF898C81)),
children: [ children: [
TextSpan( TextSpan(
text: AppLocalizations.of( text: AppLocalizations.of(
context, context,
)! )!
.terms_conditions, style: TextStyle( .terms_conditions,
style: TextStyle(
color: Color(0xFF985400), color: Color(0xFF985400),
// decoration: TextDecoration.underline, // decoration: TextDecoration.underline,
fontWeight: FontWeight fontWeight: FontWeight
@ -671,16 +722,20 @@ class _ProfileScreenState extends State<ProfileScreen> {
TextSpan( TextSpan(
text: AppLocalizations.of( text: AppLocalizations.of(
context, context,
)!.t_and, )!
style: TextStyle(color: Color(0xFF898C81)), .t_and,
style: TextStyle(color: Color(0xFF898C81)),
), ),
TextSpan( TextSpan(
text: AppLocalizations.of( text: AppLocalizations.of(
context, context,
)!.privacy_policy, style: TextStyle( )!
.privacy_policy,
style: TextStyle(
color: Color(0xFF985400), color: Color(0xFF985400),
// decoration: TextDecoration.underline, // decoration: TextDecoration.underline,
fontWeight: FontWeight.w600, // Makes the text bold fontWeight: FontWeight
.w600, // Makes the text bold
decorationColor: Color(0xFF985400), decorationColor: Color(0xFF985400),
decorationThickness: 1, decorationThickness: 1,
), ),
@ -734,8 +789,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
context.go('/createNewPw/$userId/$email'); context.go('/createNewPw/$userId/$email');
}, },
child: Text( child: Text(
AppLocalizations.of(context)! AppLocalizations.of(context)!.change_password,
.change_password,
style: TextStyle( style: TextStyle(
color: Color(0xFF648CBA), color: Color(0xFF648CBA),
fontSize: 14, fontSize: 14,

View File

@ -11,7 +11,7 @@ extension Dialogs on BuildContext {
context: this, context: this,
builder: (loaderContext) { builder: (loaderContext) {
if (!ctxWaiter.isCompleted) ctxWaiter.complete(loaderContext); if (!ctxWaiter.isCompleted) ctxWaiter.complete(loaderContext);
return const Dialog( return Dialog(
child: LinearProgressIndicator(), child: LinearProgressIndicator(),
); );
}, },
@ -111,6 +111,18 @@ extension Dialogs on BuildContext {
this, this,
rootNavigator: true, rootNavigator: true,
).pop, ).pop,
style: TextButton.styleFrom(
// backgroundColor: Colors.white, // Background color
foregroundColor: Color(0xFF92722A), // Font (text) color
side: BorderSide(
color: Color(0xFF92722A)), // Border outline color
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(8), // Optional: Rounded corners
),
padding: EdgeInsets.symmetric(
horizontal: 16, vertical: 12), // Optional: Padding
),
child: const Text('Return'), child: const Text('Return'),
), ),
if (extraAction != null) extraAction, if (extraAction != null) extraAction,

View File

@ -698,19 +698,31 @@ class LoginRoute extends HookConsumerWidget {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: Text("Exit App"), title: Text( context.translate(
content: Text("Are you sure you want to exit?"), 'Exit App',
'الخروج من التطبيق',
),),
content: Text( context.translate(
'Are you sure you want to exit?',
'هل أنت متأكد أنك تريد الخروج؟',
),),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(), // Close dialog onPressed: () => Navigator.of(context).pop(), // Close dialog
child: Text("Cancel"), child: Text( context.translate(
'Cancel',
'إلغاء',
),),
), ),
TextButton( TextButton(
onPressed: () => SystemNavigator.pop(), // Exit the app onPressed: () => SystemNavigator.pop(), // Exit the app
child: Text("Exit"), child: Text( context.translate(
'Exit',
'خروج',
),),
), ),
], ],
), ),
); );
} }
} }

View File

@ -167,6 +167,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/infrastructure/data/p_auth_repo.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart';
@ -183,17 +185,73 @@ class MyHomePage extends ConsumerStatefulWidget {
} }
class _MyHomePageState extends ConsumerState<MyHomePage> { class _MyHomePageState extends ConsumerState<MyHomePage> {
final PAuthRepo _authRepo = PAuthRepo();
Future<void> logout(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
await _authRepo.logout();
prefs.clear();
context.go('/login'); // Redirect to login after logout
}
void _showExitConfirmation(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
context.translate(
'Logout',
'تسجيل الخروج',
),
),
content: Text(
context.translate(
'Are you sure you want to logout?',
'هل أنت متأكد أنك تريد تسجيل الخروج؟',
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(), // Close dialog
child: Text(
context.translate(
'Cancel',
'إلغاء',
),
),
),
TextButton(
onPressed: () => logout(context), // Exit the app
child: Text(
context.translate(
'Logout',
'تسجيل الخروج',
),
),
),
],
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold( return PopScope(
title: Center( canPop: false, // Allow back navigation only if not login screen
child: SizedBox( onPopInvokedWithResult: (didPop, result) {
height: myheight / 5, if (didPop) return;
width: mywidth / 3, _showExitConfirmation(context); // Show exit confirmation dialog
child: Image(image: AssetImage('assets/logos/uae_stat.png')))), },
body: EconomyStatsWidget(), child: BaseScaffold(
title: Center(
child: SizedBox(
height: myheight / 5,
width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png')))),
body: EconomyStatsWidget(),
),
); );
} }
} }

View File

@ -62,9 +62,10 @@ class _BookMarkState extends ConsumerState<BookMark> {
final filteredList = final filteredList =
dataList.where((item) => item['isBookmark'] == true).toList(); dataList.where((item) => item['isBookmark'] == true).toList();
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
title: Text('Bookmark'), title: Text('Bookmark'),

View File

@ -425,9 +425,10 @@ class _EditProfileState extends State<EditProfile> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
title: Text( title: Text(

View File

@ -238,9 +238,10 @@ class _FeedbackFormState extends State<FeedbackForm>
final userName = GoRouterState.of(context).extra as String? ?? 'Guest User'; final userName = GoRouterState.of(context).extra as String? ?? 'Guest User';
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
// title: Text("Feedback"), // title: Text("Feedback"),
@ -550,8 +551,8 @@ class _FeedbackFormState extends State<FeedbackForm>
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
Text( Text(
AppLocalizations.of(context)!.feedback_message, AppLocalizations.of(context)!.feedback_message,
style: TextStyle(fontSize: 16, color: Color(0xFF898C81)), style: TextStyle(fontSize: 16, color: Color(0xFF898C81)),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
@ -602,9 +603,9 @@ AppLocalizations.of(context)!.feedback_message,
// Icon(Icons.error, size: 80, color: Colors.red), // Icon(Icons.error, size: 80, color: Colors.red),
const SizedBox(height: 20), const SizedBox(height: 20),
Text( Text(
AppLocalizations.of(context)!.failed_to_sharefeedback, AppLocalizations.of(context)!.failed_to_sharefeedback,
style: TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color(0xFF414042)), color: Color(0xFF414042)),
@ -753,10 +754,9 @@ AppLocalizations.of(context)!.feedback_message,
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
AppLocalizations.of(context)!.formError, AppLocalizations.of(context)!.formError,
// "Please correct the errors before submitting." // "Please correct the errors before submitting."
) )),
),
); );
return; return;
} }
@ -786,10 +786,10 @@ AppLocalizations.of(context)!.feedback_message,
// await sendFeedbackEmail(feedbackData, createdTime); // await sendFeedbackEmail(feedbackData, createdTime);
await _removeFeedbackText(); await _removeFeedbackText();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text(AppLocalizations.of(context)!.feedback_submitted), content: Text(AppLocalizations.of(context)!.feedback_submitted),
), ),
); );
setState(() { setState(() {
_isFeedbackSubmitted = true; _isFeedbackSubmitted = true;
_isFeedbackFailed = false; _isFeedbackFailed = false;
@ -798,12 +798,11 @@ AppLocalizations.of(context)!.feedback_message,
} }
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text( SnackBar(
// "Failed to submit feedback: $e" content: Text(
// "Failed to submit feedback: $e"
AppLocalizations.of(context)!.feedback_failed(e.toString()), AppLocalizations.of(context)!.feedback_failed(e.toString()),
) )),
),
); );
setState(() { setState(() {
_isFeedbackFailed = true; // Update state to show failure message _isFeedbackFailed = true; // Update state to show failure message

View File

@ -144,7 +144,8 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
TextSpan( TextSpan(
text: newStatus, text: newStatus,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, // Makes newStatus bold fontWeight:
FontWeight.bold, // Makes newStatus bold
fontSize: 18, fontSize: 18,
color: Color(0xFF898C81), color: Color(0xFF898C81),
), ),
@ -175,74 +176,77 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
children: [ children: [
SizedBox( SizedBox(
width: 100, // Set the desired width width: 100, // Set the desired width
child: child: TextButton(
TextButton( onPressed: () {
onPressed: () { Navigator.of(context)
Navigator.of(context) .pop(); // Close dialog without changing status
.pop(); // Close dialog without changing status },
}, style: TextButton.styleFrom(
style: TextButton.styleFrom( shape: RoundedRectangleBorder(
shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(
borderRadius: BorderRadius.circular( 10.0), // Adjust the radius as needed
10.0), // Adjust the radius as needed ),
side: BorderSide(
color: Color(0xFFAA8E83), // Set the outline color
width: 1, // Set the border width
),
), ),
side: BorderSide( child: Text(
color: Color(0xFFAA8E83), // Set the outline color AppLocalizations.of(context)!.no,
width: 1, // Set the border width style: TextStyle(
color: Color(0xFFAA8E83),
fontSize: 16,
),
), ),
), ),
child: Text(AppLocalizations.of(context)!.no,
style: TextStyle(color: Color(0xFFAA8E83),
fontSize: 16,
),),
),
), ),
SizedBox( SizedBox(
width: 100, // Set the desired width width: 100, // Set the desired width
child: child: TextButton(
TextButton( onPressed: () async {
onPressed: () async { try {
try { // Update status in PocketBase
// Update status in PocketBase await _pb.collection('users').update(
await _pb.collection('users').update( user.id, // User's unique ID
user.id, // User's unique ID body: {
body: { 'status': newStatus, // Update status
'status': newStatus, // Update status 'verified': newStatus == 'Approved' ? true : false,
'verified': newStatus == 'Approved' ? true : false, 'reviewed': true,
'reviewed': true, },
}, );
);
// Update local state // Update local state
// setState(() { // setState(() {
// user.status = newStatus; // user.status = newStatus;
// }); // });
fetchUnverifiedUsers(); fetchUnverifiedUsers();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Status updated successfully!')), SnackBar(
); content: Text('Status updated successfully!')),
} catch (e) { );
ScaffoldMessenger.of(context).showSnackBar( } catch (e) {
SnackBar(content: Text('Error updating status: $e')), ScaffoldMessenger.of(context).showSnackBar(
); SnackBar(content: Text('Error updating status: $e')),
} );
Navigator.of(context).pop(); // Close dialog }
}, Navigator.of(context).pop(); // Close dialog
style: TextButton.styleFrom( },
backgroundColor: Color(0xFFAA8E83), // Set background color style: TextButton.styleFrom(
foregroundColor: Colors.white, backgroundColor:
shape: RoundedRectangleBorder( Color(0xFFAA8E83), // Set background color
borderRadius: foregroundColor: Colors.white,
BorderRadius.circular(10.0), // Set text color shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10.0), // Set text color
),
),
child: Text(
// 'Yes',
AppLocalizations.of(context)!.yes,
style: TextStyle(color: Colors.white, fontSize: 16),
), ),
), ),
child: Text( ),
// 'Yes',
AppLocalizations.of(context)!.yes,
style: TextStyle(color: Colors.white,
fontSize: 16),
),
),),
], ],
) )
], ],
@ -262,9 +266,10 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
return PopScope( return PopScope(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) { onPopInvokedWithResult: (didPop, result) {
if (didPop) return; if (didPop) return;
context.go('/myhomepage'); context.go('/myhomepage'); // Show exit confirmation dialog
}, },
child: BaseScaffold( child: BaseScaffold(
// title: Text("Manage User"), // title: Text("Manage User"),
@ -285,185 +290,186 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
// ), // ),
// ), // ),
// onChanged: filterUsers, // onChanged: filterUsers,
// ), // ),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(30.0), borderRadius: BorderRadius.circular(30.0),
border: Border.all(width: 2, color: Color(0xFFAA8E83)), border: Border.all(width: 2, color: Color(0xFFAA8E83)),
),
child: TextField(
decoration: InputDecoration(
hintText: AppLocalizations.of(context)!.search,
prefixIcon: Image.asset(
MiscIconAssetPath.search,
width: 20,
height: 20,
),
// ,prefixIcon: Icon(
// Icons.search,
// color: Color(0xFFAA8E83),
// ),
border: InputBorder.none,
contentPadding:
EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
), ),
onChanged: filterUsers, child: TextField(
), decoration: InputDecoration(
), hintText: AppLocalizations.of(context)!.search,
SizedBox(height: myheight / 40), prefixIcon: Image.asset(
filteredUserData.isEmpty MiscIconAssetPath.search,
? Center( width: 20,
child: Padding( height: 20,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: myheight/5),
// Icon(Icons.search,
// size: 60, color: Colors.grey),
Image.asset(
MiscIconAssetPath.group,
width: 60,
height: 60,
),
SizedBox(height: 15),
// Space between icon and text
Text(
"No results found",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.grey[700],
),
),
SizedBox(height: 12), // Space between texts
FittedBox(
child: Text(
"We couldn't find anything matching your search.",
style: TextStyle(
fontSize: 18, color: Color(0xFF898C81)),
textAlign: TextAlign.center,
),),
],
),
), ),
) // ,prefixIcon: Icon(
: SingleChildScrollView( // Icons.search,
scrollDirection: Axis.horizontal, // color: Color(0xFFAA8E83),
child: ConstrainedBox( // ),
constraints: BoxConstraints( border: InputBorder.none,
minWidth: MediaQuery.of(context).size.width, contentPadding: EdgeInsets.symmetric(
vertical: 15.0, horizontal: 20.0),
), ),
child: DataTable( onChanged: filterUsers,
sortColumnIndex: _sortColumnIndex, ),
sortAscending: _isAscending, ),
columns: [ SizedBox(height: myheight / 40),
DataColumn( filteredUserData.isEmpty
label: Text( ? Center(
AppLocalizations.of(context)!.user_name, child: Padding(
), padding: const EdgeInsets.all(16.0),
onSort: (columnIndex, ascending) { child: Column(
_sort((user) => user.userName.toLowerCase(), mainAxisSize: MainAxisSize.min,
columnIndex, ascending); children: [
}, SizedBox(height: myheight / 5),
),
DataColumn( // Icon(Icons.search,
label: Text( // size: 60, color: Colors.grey),
AppLocalizations.of(context)!.email_id, Image.asset(
), MiscIconAssetPath.group,
onSort: (columnIndex, ascending) { width: 60,
_sort((user) => user.emailId.toLowerCase(), height: 60,
columnIndex, ascending); ),
},
), SizedBox(height: 15),
DataColumn( // Space between icon and text
label: Text( Text(
AppLocalizations.of(context)!.reg_date, "No results found",
), style: TextStyle(
onSort: (columnIndex, ascending) { fontSize: 24,
_sort( fontWeight: FontWeight.bold,
(user) => DateFormat('dd/MM/yyyy') color: Colors.grey[700],
.parse(user.registrationDate),
columnIndex,
ascending,
);
},
),
DataColumn(
label: Text(
AppLocalizations.of(context)!.status,
),
onSort: (columnIndex, ascending) {
_sort((user) => user.status.toLowerCase(),
columnIndex, ascending);
},
),
],
rows: filteredUserData.isEmpty
? [
DataRow(
cells: List<DataCell>.generate(
4, // Ensure it matches the number of DataColumns
(index) => DataCell(
index == 0
? Text(
'No results found',
style: TextStyle(
fontStyle:
FontStyle.italic),
)
: const Text(
''), // Empty cells for other columns
placeholder: true,
),
), ),
), ),
]
: filteredUserData.map((user) { SizedBox(height: 12), // Space between texts
return DataRow( FittedBox(
cells: [ child: Text(
DataCell(Text(user.userName)), "We couldn't find anything matching your search.",
DataCell(Text(user.emailId)), style: TextStyle(
DataCell(Text(user.registrationDate)), fontSize: 18, color: Color(0xFF898C81)),
DataCell( textAlign: TextAlign.center,
DropdownButton<String>( ),
value: user.status, ),
items: statusOptions.entries ],
.map((status) { ),
return DropdownMenuItem<String>( ),
value: status.key, )
child: Text( : SingleChildScrollView(
status.value, scrollDirection: Axis.horizontal,
style: TextStyle( child: ConstrainedBox(
color: getStatusColor( constraints: BoxConstraints(
status.key), minWidth: MediaQuery.of(context).size.width,
), ),
), child: DataTable(
); sortColumnIndex: _sortColumnIndex,
}).toList(), sortAscending: _isAscending,
onChanged: (newStatus) { columns: [
print(user); DataColumn(
if (newStatus != null) { label: Text(
_showConfirmationDialog( AppLocalizations.of(context)!.user_name,
user, newStatus); ),
} onSort: (columnIndex, ascending) {
}, _sort((user) => user.userName.toLowerCase(),
columnIndex, ascending);
},
),
DataColumn(
label: Text(
AppLocalizations.of(context)!.email_id,
),
onSort: (columnIndex, ascending) {
_sort((user) => user.emailId.toLowerCase(),
columnIndex, ascending);
},
),
DataColumn(
label: Text(
AppLocalizations.of(context)!.reg_date,
),
onSort: (columnIndex, ascending) {
_sort(
(user) => DateFormat('dd/MM/yyyy')
.parse(user.registrationDate),
columnIndex,
ascending,
);
},
),
DataColumn(
label: Text(
AppLocalizations.of(context)!.status,
),
onSort: (columnIndex, ascending) {
_sort((user) => user.status.toLowerCase(),
columnIndex, ascending);
},
),
],
rows: filteredUserData.isEmpty
? [
DataRow(
cells: List<DataCell>.generate(
4, // Ensure it matches the number of DataColumns
(index) => DataCell(
index == 0
? Text(
'No results found',
style: TextStyle(
fontStyle:
FontStyle.italic),
)
: const Text(
''), // Empty cells for other columns
placeholder: true,
),
),
), ),
), ]
], : filteredUserData.map((user) {
); return DataRow(
}).toList(), cells: [
), DataCell(Text(user.userName)),
), DataCell(Text(user.emailId)),
), DataCell(Text(user.registrationDate)),
DataCell(
DropdownButton<String>(
value: user.status,
items: statusOptions.entries
.map((status) {
return DropdownMenuItem<String>(
value: status.key,
child: Text(
status.value,
style: TextStyle(
color: getStatusColor(
status.key),
),
),
);
}).toList(),
onChanged: (newStatus) {
print(user);
if (newStatus != null) {
_showConfirmationDialog(
user, newStatus);
}
},
),
),
],
);
}).toList(),
),
),
),
], ],
),
), ),
), ),
),
), ),
); );
} }

View File

@ -51,7 +51,7 @@ class _UserguideState extends State<Userguide> {
dividerColor: Colors.grey[300], dividerColor: Colors.grey[300],
appbarColor: Colors.white, appbarColor: Colors.white,
title: Padding( title: Padding(
padding:EdgeInsets.only(bottom:8.0), padding:EdgeInsets.only(bottom:0.0),
child: Text('User Guide'), child: Text('User Guide'),
) , ) ,
body: Container( body: Container(

View File

@ -14,6 +14,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
import 'package:uae_stat/config/injector.dart'; import 'package:uae_stat/config/injector.dart';
import 'package:uae_stat/domain/repos/t_auth_repo.dart'; import 'package:uae_stat/domain/repos/t_auth_repo.dart';
import 'package:uae_stat/infrastructure/data/p_auth_repo.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/bottom_bar_asset_icon_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/bottom_bar_asset_icon_path.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/drawer_asset_icon_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/drawer_asset_icon_path.dart';
@ -296,7 +297,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
elevation: 0, elevation: 0,
), ),
child: Text( child: Text(
// 'Skip', // 'Skip',
AppLocalizations.of(context)!.skip, AppLocalizations.of(context)!.skip,
style: TextStyle( style: TextStyle(
@ -431,7 +432,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
elevation: 0, elevation: 0,
), ),
child: Text( child: Text(
// 'Skip', // 'Skip',
AppLocalizations.of(context)!.skip, AppLocalizations.of(context)!.skip,
style: TextStyle( style: TextStyle(
@ -489,7 +490,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
backgroundColor: Colors.white, backgroundColor: Colors.white,
elevation: 0, elevation: 0,
), ),
child: Text( child: Text(
AppLocalizations.of(context)!.got_it, AppLocalizations.of(context)!.got_it,
style: TextStyle( style: TextStyle(
color: Color(0xFF7DAFBC), color: Color(0xFF7DAFBC),
@ -602,18 +603,26 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
} }
} }
Future<void> logout() async { // Future<void> logout() async {
// final prefs = await SharedPreferences.getInstance();
// // setState(() {
// // isLoggedOut = true;
// // });
// // prefs.clear();
// await _repo.logout();
// // state = const AsyncData(null);
// // _pb.authStore.clear();
// // await _secureStorage.delete(key: "FlutterSecureStorage.session");
// prefs.clear();
// context.go('/login');
// }
final PAuthRepo _authRepo = PAuthRepo();
Future<void> logout(BuildContext context) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
// setState(() { await _authRepo.logout();
// isLoggedOut = true;
// });
// prefs.clear();
await _repo.logout();
// state = const AsyncData(null);
// _pb.authStore.clear();
// await _secureStorage.delete(key: "FlutterSecureStorage.session");
prefs.clear(); prefs.clear();
context.go('/login'); context.go('/login'); // Redirect to login after logout
} }
@override @override
@ -628,7 +637,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBar( appBar: AppBar(
// title: widget.title, // title: widget.title,
title: Align( title: Align(
alignment: Alignment.centerLeft, // Aligns the title to the left alignment: Alignment.centerLeft, // Aligns the title to the left
child: widget.title, child: widget.title,
), ),
@ -642,7 +651,8 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
color: widget.dividerColor, // Line color color: widget.dividerColor, // Line color
height: 1, // Line thickness height: 1, // Line thickness
), ),
): null, )
: null,
actions: widget.actions ?? actions: widget.actions ??
[ [
// IconButton( // IconButton(
@ -675,7 +685,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
), ),
Positioned( Positioned(
top: 5, top: 8,
right: 10, right: 10,
child: Builder( child: Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
@ -694,177 +704,176 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
), ),
drawer: Drawer( drawer: Drawer(
backgroundColor: Colors.white, backgroundColor: Colors.white,
child: Column(children: [ child: Column(children: [
Expanded( Expanded(
child: ListView( child: ListView(
children: [
children: [ DrawerHeader(
DrawerHeader( child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.stretch,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [ children: [
SizedBox( Row(
width: mywidth / 8, children: [
child: Image( SizedBox(
image: AssetImage('assets/logos/fcsc.png'), width: mywidth / 8,
child: Image(
image: AssetImage('assets/logos/fcsc.png'),
),
),
],
),
Divider(),
InkWell(
onTap: () {
if (userId != 'guest') context.go('/editProfile');
},
child: Row(
children: [
SizedBox(
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(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
if (userId == "guest") ...[
Text(userName ?? 'Guest User'),
] else ...[
Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),
]
],
),
],
), ),
), ),
], ],
), ),
Divider(), ),
InkWell( if (userId != 'guest')
onTap: () { ListTile(
if (userId != 'guest') context.go('/editProfile'); leading: Image.asset(
}, DrawerAssetIconPath.feedback,
child: Row( color: Colors.black,
children: [ width: 20,
SizedBox( height: 20,
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(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
if (userId == "guest") ...[
Text(userName ?? 'Guest User'),
] else ...[
Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),
]
],
),
],
), ),
// title: const Text('Feedback'),
title: Text(AppLocalizations.of(context)!.feedback_title),
onTap: () => context.go('/feedback', extra: userName),
), ),
], if (role == 'admin')
), ListTile(
), leading: Image.asset(
if (userId != 'guest') DrawerAssetIconPath.manageUser,
ListTile( color: Colors.black,
leading: Image.asset( width: 20,
DrawerAssetIconPath.feedback, height: 20,
color: Colors.black, ),
width: 20, // title: Text('Manage User'),
height: 20, title: Text(
AppLocalizations.of(context)!.manage_user,
),
onTap: () => context.go('/manageuser'),
),
ListTile(
leading: Icon(Icons.bookmarks_outlined),
// title: const Text('Bookmark'),
title: Text(
AppLocalizations.of(context)!.bookmark_title,
),
onTap: () => context.go('/bookmark'),
), ),
// title: const Text('Feedback'), ListTile(
title: Text(AppLocalizations.of(context)!.feedback_title), leading: Image.asset(
onTap: () => context.go('/feedback', extra: userName), DrawerAssetIconPath.guide,
), color: Colors.black,
if (role == 'admin') width: 20,
ListTile( height: 20,
leading: Image.asset( ),
DrawerAssetIconPath.manageUser, // title: const Text('User Guide'),
color: Colors.black, title: Text(AppLocalizations.of(context)!.guide_title),
width: 20, onTap: () => context.go('/user-guide'),
height: 20,
), ),
// title: Text('Manage User'), if (userId != 'guest')
title: Text( ListTile(
AppLocalizations.of(context)!.manage_user, leading: Icon(Icons.logout),
), // title: const Text('Logout'),
onTap: () => context.go('/manageuser'), title: Text(AppLocalizations.of(context)!.logout),
), onTap: () => logout(context),
ListTile( ),
leading: Icon(Icons.bookmarks_outlined), if (userId == 'guest')
// title: const Text('Bookmark'), ListTile(
title: Text( leading: Icon(Icons.login),
AppLocalizations.of(context)!.bookmark_title, // title: const Text('Login'),
), title: Text(AppLocalizations.of(context)!.login_title),
onTap: () => context.go('/bookmark'), onTap: () => context.go('/login'),
),
if (userId == 'guest')
ListTile(
leading: Icon(Icons.app_registration),
// title: const Text('Register'),
title: Text(AppLocalizations.of(context)!.register_title),
onTap: () => context.go('/register'),
),
],
), ),
ListTile( ),
leading: Image.asset( Padding(
DrawerAssetIconPath.guide, padding: const EdgeInsets.only(bottom: 16.0),
color: Colors.black, child: FutureBuilder<String>(
width: 20, future: _getAppVersion(), // Function to get the app version
height: 20, builder: (context, snapshot) {
), if (snapshot.connectionState == ConnectionState.waiting) {
// title: const Text('User Guide'), return Text(
title: Text(AppLocalizations.of(context)!.guide_title), 'Loading version...',
onTap: () => context.go('/user-guide'), style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.center,
);
} else if (snapshot.hasError) {
return Text(
'Error fetching version',
style: TextStyle(fontSize: 12, color: Colors.red),
textAlign: TextAlign.center,
);
} else {
return Text(
'Version ${snapshot.data}',
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.center,
);
}
},
), ),
if (userId != 'guest') ),
ListTile( ])),
leading: Icon(Icons.logout),
// title: const Text('Logout'),
title: Text(AppLocalizations.of(context)!.logout),
onTap: () => logout(),
),
if (userId == 'guest')
ListTile(
leading: Icon(Icons.login),
// title: const Text('Login'),
title: Text(AppLocalizations.of(context)!.login_title),
onTap: () => context.go('/login'),
),
if (userId == 'guest')
ListTile(
leading: Icon(Icons.app_registration),
// title: const Text('Register'),
title: Text(AppLocalizations.of(context)!.register_title),
onTap: () => context.go('/register'),
),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: FutureBuilder<String>(
future: _getAppVersion(), // Function to get the app version
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Text(
'Loading version...',
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.center,
);
} else if (snapshot.hasError) {
return Text(
'Error fetching version',
style: TextStyle(fontSize: 12, color: Colors.red),
textAlign: TextAlign.center,
);
} else {
return Text(
'Version ${snapshot.data}',
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.center,
);
}
},
),
),
])),
bottomNavigationBar: BottomNavigationBar( bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.white, backgroundColor: Colors.white,
currentIndex: _getSelectedIndex(currentRoute), currentIndex: _getSelectedIndex(currentRoute),