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(),
), ),
); );

View File

@ -336,11 +336,14 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
); );
} }
return Scaffold( return PopScope(
canPop: false, // Allow back navigation only if not login screen
body: onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
Column( context.go('/login'); // Show exit confirmation dialog
},
child: Scaffold(
body: Column(
children: [ children: [
Align( Align(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
@ -371,9 +374,7 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
Container( Container(
height: MediaQuery.of(context).size.height / 1.2, height: MediaQuery.of(context).size.height / 1.2,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(children: [
children : [
registrationSuccess registrationSuccess
? Padding( ? Padding(
padding: const EdgeInsets.all(20.0), padding: const EdgeInsets.all(20.0),
@ -381,7 +382,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox(height: screenheight / 8), SizedBox(height: screenheight / 8),
buildIconContainer(Icons.report, Color(0xFF7DAFBC)), buildIconContainer(
Icons.report, Color(0xFF7DAFBC)),
SizedBox(height: 20), SizedBox(height: 20),
Text( Text(
context.translate( context.translate(
@ -408,7 +410,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
ElevatedButton( ElevatedButton(
onPressed: () => {context.go('/')}, onPressed: () => {context.go('/')},
child: Text( child: Text(
context.translate('Go to Login', 'اذهب إلى تسجيل الدخول'), context.translate(
'Go to Login', 'اذهب إلى تسجيل الدخول'),
), ),
), ),
SizedBox(height: screenheight / 5), SizedBox(height: screenheight / 5),
@ -437,7 +440,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
buildIconContainer(Icons.report, Colors.red), buildIconContainer(Icons.report, Colors.red),
SizedBox(height: 20), SizedBox(height: 20),
Text( Text(
context.translate('Sorry ${_usernameController.text}!', context.translate(
'Sorry ${_usernameController.text}!',
'آسف ${_usernameController.text}!'), 'آسف ${_usernameController.text}!'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
@ -470,7 +474,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
}) })
}, },
child: Text( child: Text(
context.translate('Retry', 'أعد المحاولة'), context.translate(
'Retry', 'أعد المحاولة'),
), ),
), ),
SizedBox(height: screenheight / 5), SizedBox(height: screenheight / 5),
@ -489,7 +494,6 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
], ],
), ),
) )
: Form( : Form(
key: _formKey, key: _formKey,
child: SingleChildScrollView( child: SingleChildScrollView(
@ -499,32 +503,41 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
SizedBox(height: screenheight / 60), SizedBox(height: screenheight / 60),
Text( Text(
// 'Register', // 'Register',
AppLocalizations.of(context)!.register_title, AppLocalizations.of(context)!
.register_title,
style: TextStyle( style: TextStyle(
fontSize: 32, fontWeight: FontWeight.w400), fontSize: 32,
fontWeight: FontWeight.w400),
), ),
SizedBox(height: 10), SizedBox(height: 10),
Text(AppLocalizations.of(context)!.register_details), Text(AppLocalizations.of(context)!
.register_details),
SizedBox(height: 20), SizedBox(height: 20),
// Display this if registration is pending approval // Display this if registration is pending approval
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 5.0, bottom: 10, left: 30, right: 30), top: 5.0,
bottom: 10,
left: 30,
right: 30),
child: TextFormField( child: TextFormField(
controller: _usernameController, controller: _usernameController,
// focusNode: _focusNodes[0], // focusNode: _focusNodes[0],
decoration: InputDecoration( decoration: InputDecoration(
// hintText: _showHints[0] ? 'Username' : null, // hintText: _showHints[0] ? 'Username' : null,
hintText: _showHints[0] hintText: _showHints[0]
? AppLocalizations.of(context)!.register_name ? AppLocalizations.of(context)!
.register_name
: null, : null,
prefixIconConstraints: const BoxConstraints( prefixIconConstraints:
const BoxConstraints(
maxWidth: 25 + 16 + 10, maxWidth: 25 + 16 + 10,
maxHeight: 25 + (8 * 2), maxHeight: 25 + (8 * 2),
), ),
prefixIcon: Padding( prefixIcon: Padding(
padding: const EdgeInsetsDirectional.only( padding: const EdgeInsetsDirectional
.only(
start: 16, start: 16,
end: 10, end: 10,
), ),
@ -533,8 +546,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
fit: BoxFit.fitHeight, fit: BoxFit.fitHeight,
height: 25, height: 25,
width: 25, width: 25,
color: color: MyTheme.topicColor(
MyTheme.topicColor(IndicatorTopic.economy) IndicatorTopic.economy)
.shade300, .shade300,
), ),
), ),
@ -546,7 +559,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
// ), // ),
// border: OutlineInputBorder(), // border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
@ -554,38 +568,52 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
width: 1), // Enabled border width: 1), // Enabled border
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder:
borderRadius: BorderRadius.circular(10), OutlineInputBorder(
borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width:
1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB), hintStyle: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, color: Color(0xFFC3C6CB),
fontSize:
registerLocale?.languageCode ==
'ar'
? 14
: 16,
), ),
), ),
validator: _validateUsername, validator: _validateUsername,
maxLength: maxLength:
40, // Set the maximum length to 20 characters 40, // Set the maximum length to 20 characters
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLengthEnforcement:
MaxLengthEnforcement.enforced,
), ),
), ),
SizedBox(height: 15), SizedBox(height: 15),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 5.0, bottom: 10, left: 30, right: 30), top: 5.0,
bottom: 10,
left: 30,
right: 30),
child: TextFormField( child: TextFormField(
controller: _emailController, controller: _emailController,
// focusNode: _focusNodes[1], // focusNode: _focusNodes[1],
@ -596,12 +624,14 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
.enter_your_email .enter_your_email
: null, : null,
// _showHints[1] ? 'Enter your email' : null, // _showHints[1] ? 'Enter your email' : null,
prefixIconConstraints: const BoxConstraints( prefixIconConstraints:
const BoxConstraints(
maxWidth: 25 + 16 + 10, maxWidth: 25 + 16 + 10,
maxHeight: 25 + (8 * 2), maxHeight: 25 + (8 * 2),
), ),
prefixIcon: Padding( prefixIcon: Padding(
padding: const EdgeInsetsDirectional.only( padding: const EdgeInsetsDirectional
.only(
start: 16, start: 16,
end: 10, end: 10,
), ),
@ -610,15 +640,16 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
fit: BoxFit.fitHeight, fit: BoxFit.fitHeight,
height: 20, height: 20,
width: 25, width: 25,
color: color: MyTheme.topicColor(
MyTheme.topicColor(IndicatorTopic.economy) IndicatorTopic.economy)
.shade100, .shade100,
), ),
), ),
// border: OutlineInputBorder(), // border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
@ -626,31 +657,42 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
width: 1), width: 1),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder:
borderRadius: BorderRadius.circular(10), OutlineInputBorder(
borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width:
1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB), hintStyle: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, color: Color(0xFFC3C6CB),
fontSize:
registerLocale?.languageCode ==
'ar'
? 14
: 16,
), ),
), ),
validator: _validateEmail, validator: _validateEmail,
maxLength: 320, maxLength: 320,
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLengthEnforcement:
MaxLengthEnforcement.enforced,
inputFormatters: [ inputFormatters: [
LengthLimitingTextInputFormatter( LengthLimitingTextInputFormatter(
320), // Limit to 320 characters 320), // Limit to 320 characters
@ -660,7 +702,10 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
SizedBox(height: 15), SizedBox(height: 15),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 5.0, bottom: 10, left: 30, right: 30), top: 5.0,
bottom: 10,
left: 30,
right: 30),
child: TextFormField( child: TextFormField(
controller: _passwordController, controller: _passwordController,
// focusNode: _focusNodes[2], // focusNode: _focusNodes[2],
@ -671,12 +716,14 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
.enter_your_password .enter_your_password
: null, : null,
// _showHints[2] ? 'Enter your password' : null, // _showHints[2] ? 'Enter your password' : null,
prefixIconConstraints: const BoxConstraints( prefixIconConstraints:
const BoxConstraints(
maxWidth: 25 + 16 + 10, maxWidth: 25 + 16 + 10,
maxHeight: 25 + (8 * 2), maxHeight: 25 + (8 * 2),
), ),
prefixIcon: Padding( prefixIcon: Padding(
padding: const EdgeInsetsDirectional.only( padding: const EdgeInsetsDirectional
.only(
start: 16, start: 16,
end: 10, end: 10,
), ),
@ -685,8 +732,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
fit: BoxFit.fitHeight, fit: BoxFit.fitHeight,
height: 25, height: 25,
width: 25, width: 25,
color: color: MyTheme.topicColor(
MyTheme.topicColor(IndicatorTopic.economy) IndicatorTopic.economy)
.shade300, .shade300,
), ),
), ),
@ -705,7 +752,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
icon: Image.asset( icon: Image.asset(
_obscurePassword _obscurePassword
? MiscIconAssetPath.visibilityOff ? MiscIconAssetPath
.visibilityOff
: MiscIconAssetPath.visibleOn, : MiscIconAssetPath.visibleOn,
color: Color( color: Color(
@ -716,13 +764,15 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
onPressed: () { onPressed: () {
setState(() { setState(() {
_obscurePassword = !_obscurePassword; _obscurePassword =
!_obscurePassword;
}); });
}, },
), ),
// border: OutlineInputBorder(), // border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
@ -730,38 +780,52 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
width: 1), width: 1),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder:
borderRadius: BorderRadius.circular(10), OutlineInputBorder(
borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width:
1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB), hintStyle: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, color: Color(0xFFC3C6CB),
fontSize:
registerLocale?.languageCode ==
'ar'
? 14
: 16,
), ),
), ),
validator: _validatePassword, validator: _validatePassword,
maxLength: 40, maxLength: 40,
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLengthEnforcement:
MaxLengthEnforcement.enforced,
), ),
), ),
SizedBox(height: 15), SizedBox(height: 15),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 5.0, bottom: 10, left: 30, right: 30), top: 5.0,
bottom: 10,
left: 30,
right: 30),
child: TextFormField( child: TextFormField(
controller: _confirmpasswordController, controller: _confirmpasswordController,
// focusNode: _focusNodes[3], // focusNode: _focusNodes[3],
@ -772,12 +836,14 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
.register_Confirm_password .register_Confirm_password
: null, : null,
// _showHints[3] ? 'Confirm password' : null, // _showHints[3] ? 'Confirm password' : null,
prefixIconConstraints: const BoxConstraints( prefixIconConstraints:
const BoxConstraints(
maxWidth: 25 + 16 + 10, maxWidth: 25 + 16 + 10,
maxHeight: 25 + (8 * 2), maxHeight: 25 + (8 * 2),
), ),
prefixIcon: Padding( prefixIcon: Padding(
padding: const EdgeInsetsDirectional.only( padding: const EdgeInsetsDirectional
.only(
start: 16, start: 16,
end: 10, end: 10,
), ),
@ -786,8 +852,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
fit: BoxFit.fitHeight, fit: BoxFit.fitHeight,
height: 25, height: 25,
width: 25, width: 25,
color: color: MyTheme.topicColor(
MyTheme.topicColor(IndicatorTopic.economy) IndicatorTopic.economy)
.shade300, .shade300,
), ),
), ),
@ -795,7 +861,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Image.asset( icon: Image.asset(
_obscureConfirmPassword _obscureConfirmPassword
? MiscIconAssetPath.visibilityOff ? MiscIconAssetPath
.visibilityOff
: MiscIconAssetPath.visibleOn, : MiscIconAssetPath.visibleOn,
color: Color( color: Color(
@ -814,7 +881,8 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
// borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color // borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color
// ), // ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
@ -822,31 +890,42 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
width: 1), width: 1),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder:
borderRadius: BorderRadius.circular(10), OutlineInputBorder(
borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width:
1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB), hintStyle: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, color: Color(0xFFC3C6CB),
fontSize:
registerLocale?.languageCode ==
'ar'
? 14
: 16,
), ),
), ),
validator: _validateConfirmPassword, validator: _validateConfirmPassword,
maxLength: 40, maxLength: 40,
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLengthEnforcement:
MaxLengthEnforcement.enforced,
inputFormatters: [ inputFormatters: [
LengthLimitingTextInputFormatter( LengthLimitingTextInputFormatter(
64), // Limit to 40 characters 64), // Limit to 40 characters
@ -856,9 +935,13 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
SizedBox(height: 10), SizedBox(height: 10),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 0, bottom: 10, left: 25, right: 30), top: 0,
bottom: 10,
left: 25,
right: 30),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment:
MainAxisAlignment.start,
children: [ children: [
Checkbox( Checkbox(
value: isChecked, value: isChecked,
@ -877,54 +960,82 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
), ),
Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.only(top:11.0), padding: const EdgeInsets.only(
top: 11.0),
child: Text.rich( child: Text.rich(
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.agree, text: AppLocalizations.of(
context)!
.agree,
// text: 'I agree to ', // text: 'I agree to ',
style: TextStyle( style: TextStyle(
color: Color(0xFF898C81), // Change to your desired color color: Color(
0xFF898C81), // Change to your desired color
), ),
children: [ children: [
TextSpan( TextSpan(
text: AppLocalizations.of(context)! text: AppLocalizations.of(
context)!
.terms_conditions, .terms_conditions,
// text: 'Terms & Conditions', // text: 'Terms & Conditions',
style: TextStyle( style: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, fontSize: registerLocale
fontWeight: FontWeight.bold, ?.languageCode ==
color: Color(0xFF985400), 'ar'
? 12
: 14,
fontWeight:
FontWeight.bold,
color:
Color(0xFF985400),
// Makes the text bold // Makes the text bold
// decoration: // decoration:
// TextDecoration.underline, // TextDecoration.underline,
decorationColor: Color(0xFF985400), decorationColor:
decorationThickness: 1), Color(0xFF985400),
decorationThickness:
1),
), ),
TextSpan( TextSpan(
text: AppLocalizations.of(context)! text: AppLocalizations.of(
context)!
.t_and, .t_and,
style: TextStyle( style: TextStyle(
color: Color(0xFF898C81), // Change to your desired color color: Color(
),), 0xFF898C81), // Change to your desired color
TextSpan( ),
text: AppLocalizations.of(context)!
.privacy_policy,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14,
fontFamily: 'Roboto',
color: Color(0xFF985400),
// decoration:
// TextDecoration.underline,
decorationColor: Color(0xFF648CBA),
decorationThickness: 1),
), ),
TextSpan( TextSpan(
text: AppLocalizations.of(context)! text: AppLocalizations.of(
context)!
.privacy_policy,
style: TextStyle(
fontWeight:
FontWeight.bold,
fontSize: registerLocale
?.languageCode ==
'ar'
? 12
: 14,
fontFamily: 'Roboto',
color:
Color(0xFF985400),
// decoration:
// TextDecoration.underline,
decorationColor:
Color(0xFF648CBA),
decorationThickness:
1),
),
TextSpan(
text: AppLocalizations.of(
context)!
.conditions, .conditions,
style: TextStyle( style: TextStyle(
color: Color(0xFF898C81), // Change to your desired color color: Color(
),), 0xFF898C81), // Change to your desired color
),
),
], ],
), ),
), ),
@ -935,15 +1046,21 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
), ),
if (showError) if (showError)
Row( Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment:
MainAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only(left: 30.0), padding: const EdgeInsets.only(
left: 30.0),
child: Text( child: Text(
'Required', 'Required',
style: TextStyle( style: TextStyle(
color: Color(0xFFb22222), color: Color(0xFFb22222),
fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, fontSize: registerLocale
?.languageCode ==
'ar'
? 12
: 14,
), ),
), ),
), ),
@ -952,16 +1069,22 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
SizedBox(height: 20), SizedBox(height: 20),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 5.0, bottom: 10, left: 30, right: 30), top: 5.0,
bottom: 10,
left: 30,
right: 30),
child: SizedBox( child: SizedBox(
width: screenwidth / 1, width: screenwidth / 1,
child: ElevatedButton( child: ElevatedButton(
onPressed: isRegistering ? null : _registerUser, onPressed: isRegistering
? null
: _registerUser,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Color( backgroundColor: Color(
0xFFA7887A), // Brownish color for Register 0xFFA7887A), // Brownish color for Register
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
), ),
), ),
child: Row( child: Row(
@ -972,7 +1095,11 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
AppLocalizations.of(context)! AppLocalizations.of(context)!
.register_title, .register_title,
style: TextStyle( style: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, fontSize: registerLocale
?.languageCode ==
'ar'
? 14
: 16,
color: Colors.white), color: Colors.white),
), ),
SizedBox(width: 8), SizedBox(width: 8),
@ -988,15 +1115,23 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
), ),
SizedBox(height: 15), SizedBox(height: 15),
Text( Text(
AppLocalizations.of(context)!.account_confirmation, AppLocalizations.of(context)!
.account_confirmation,
style: TextStyle( style: TextStyle(
fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, fontSize:
registerLocale?.languageCode ==
'ar'
? 12
: 14,
color: Colors.grey[600]), color: Colors.grey[600]),
), ),
SizedBox(height: 15), SizedBox(height: 15),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: 5.0, bottom: 10, left: 30, right: 30), top: 5.0,
bottom: 10,
left: 30,
right: 30),
child: SizedBox( child: SizedBox(
width: screenwidth / 1, width: screenwidth / 1,
child: ElevatedButton( child: ElevatedButton(
@ -1007,16 +1142,19 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
backgroundColor: Color( backgroundColor: Color(
0xFF82AFCB), // Blueish color for Login 0xFF82AFCB), // Blueish color for Login
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius:
BorderRadius.circular(10),
), ),
), ),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
AppLocalizations.of(context)!.login_title, AppLocalizations.of(context)!
.login_title,
style: TextStyle( style: TextStyle(
fontSize: 16, color: Colors.white), fontSize: 16,
color: Colors.white),
), ),
SizedBox(width: 8), SizedBox(width: 8),
const Icon( const Icon(
@ -1026,28 +1164,6 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
) )
], ],
), ),
// child: GestureDetector(
// onTap: () {
// // Navigate to LoginRoute
// context.go('/');
// },
// child: Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// Text(
// "Login",
// style: TextStyle(
// fontSize: 16,
// color: Colors.white,
// ),
// ),
// SizedBox(width: 8),
// Icon(Icons.arrow_forward,
// color: Colors.white),
// ],
// ),
// ),
), ),
), ),
), ),
@ -1078,6 +1194,7 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
), ),
], ],
), ),
),
); );
} }
} }

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(
@ -646,16 +698,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
Text.rich( Text.rich(
TextSpan( TextSpan(
text: AppLocalizations.of( text: AppLocalizations.of(context)!.agree,
context)!
.agree,
style: TextStyle(color: Color(0xFF898C81)), 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, )!
.t_and,
style: TextStyle(color: Color(0xFF898C81)), 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,16 +698,28 @@ 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(
canPop: false, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
_showExitConfirmation(context); // Show exit confirmation dialog
},
child: BaseScaffold(
title: Center( title: Center(
child: SizedBox( child: SizedBox(
height: myheight / 5, height: myheight / 5,
width: mywidth / 3, width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png')))), child: Image(image: AssetImage('assets/logos/uae_stat.png')))),
body: EconomyStatsWidget(), 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"),
@ -755,8 +756,7 @@ AppLocalizations.of(context)!.feedback_message,
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;
} }
@ -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(
content: Text(
// "Failed to submit feedback: $e" // "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,8 +176,7 @@ 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
@ -191,16 +191,18 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
width: 1, // Set the border width width: 1, // Set the border width
), ),
), ),
child: Text(AppLocalizations.of(context)!.no, child: Text(
style: TextStyle(color: Color(0xFFAA8E83), AppLocalizations.of(context)!.no,
style: TextStyle(
color: Color(0xFFAA8E83),
fontSize: 16, 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
@ -219,7 +221,8 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
// }); // });
fetchUnverifiedUsers(); fetchUnverifiedUsers();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Status updated successfully!')), SnackBar(
content: Text('Status updated successfully!')),
); );
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
@ -229,7 +232,8 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
Navigator.of(context).pop(); // Close dialog Navigator.of(context).pop(); // Close dialog
}, },
style: TextButton.styleFrom( style: TextButton.styleFrom(
backgroundColor: Color(0xFFAA8E83), // Set background color backgroundColor:
Color(0xFFAA8E83), // Set background color
foregroundColor: Colors.white, foregroundColor: Colors.white,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: borderRadius:
@ -239,10 +243,10 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
child: Text( child: Text(
// 'Yes', // 'Yes',
AppLocalizations.of(context)!.yes, AppLocalizations.of(context)!.yes,
style: TextStyle(color: Colors.white, style: TextStyle(color: Colors.white, fontSize: 16),
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"),
@ -305,8 +310,8 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
// color: Color(0xFFAA8E83), // color: Color(0xFFAA8E83),
// ), // ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: contentPadding: EdgeInsets.symmetric(
EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0), vertical: 15.0, horizontal: 20.0),
), ),
onChanged: filterUsers, onChanged: filterUsers,
), ),
@ -347,7 +352,8 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
style: TextStyle( style: TextStyle(
fontSize: 18, color: Color(0xFF898C81)), fontSize: 18, color: Color(0xFF898C81)),
textAlign: TextAlign.center, textAlign: TextAlign.center,
),), ),
),
], ],
), ),
), ),

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';
@ -602,18 +603,26 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
} }
} }
Future<void> logout() async { // Future<void> logout() async {
final prefs = await SharedPreferences.getInstance(); // final prefs = await SharedPreferences.getInstance();
// setState(() { // // setState(() {
// isLoggedOut = true; // // isLoggedOut = true;
// }); // // });
// // prefs.clear();
// await _repo.logout();
// // state = const AsyncData(null);
// // _pb.authStore.clear();
// // await _secureStorage.delete(key: "FlutterSecureStorage.session");
// prefs.clear(); // prefs.clear();
await _repo.logout(); // context.go('/login');
// state = const AsyncData(null); // }
// _pb.authStore.clear(); final PAuthRepo _authRepo = PAuthRepo();
// await _secureStorage.delete(key: "FlutterSecureStorage.session");
Future<void> logout(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
await _authRepo.logout();
prefs.clear(); prefs.clear();
context.go('/login'); context.go('/login'); // Redirect to login after logout
} }
@override @override
@ -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) {
@ -698,7 +708,6 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
child: Column(children: [ child: Column(children: [
Expanded( Expanded(
child: ListView( child: ListView(
children: [ children: [
DrawerHeader( DrawerHeader(
child: Column( child: Column(
@ -818,7 +827,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
leading: Icon(Icons.logout), leading: Icon(Icons.logout),
// title: const Text('Logout'), // title: const Text('Logout'),
title: Text(AppLocalizations.of(context)!.logout), title: Text(AppLocalizations.of(context)!.logout),
onTap: () => logout(), onTap: () => logout(context),
), ),
if (userId == 'guest') if (userId == 'guest')
ListTile( ListTile(