routing fix

This commit is contained in:
VINISTAN 2024-12-19 15:16:04 +05:30
commit 82a54be301
14 changed files with 537 additions and 356 deletions

View File

@ -301,7 +301,6 @@ import '../presentation/Screens/auth_verification/changepassword.dart';
import '../presentation/Screens/auth_verification/confirm_password.dart';
import '../presentation/Screens/auth_verification/create_new_pw.dart';
import '../presentation/Screens/auth_verification/otp_verification.dart';
import '../presentation/Screens/auth_verification/registration.dart';
import '../presentation/Screens/profilepage.dart';
import '../presentation/routes/auth_routes/login_route.dart';
import '../presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
@ -312,21 +311,13 @@ final GoRouter router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => LoginRoute(),
//builder: (context, state) => MyHomePage(),
//builder: (context, state) => LoginRoute(),
builder: (context, state) => MyHomePage(),
),
GoRoute(
path: '/myhomepage',
builder: (context, state) => MyHomePage(),
),
GoRoute(
path: '/login',
builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/registration',
builder: (context, state) => RegisterScreen(),
),
GoRoute(
path: '/mailverification',
builder: (context, state) => EmailVerificationScreen(

View File

@ -58,7 +58,7 @@ class _ResetPasswordScreenState extends State<Changepassword> {
//print('userDetails ->: $userData');
if (userData['items'].isNotEmpty) {
// Email exists; retrieve user ID
final userId = userData['items'][0]['id'];
// final userId = userData['items'][0]['id'];
// Proceed with OTP request
final otpResponse = await http.post(
@ -87,17 +87,15 @@ class _ResetPasswordScreenState extends State<Changepassword> {
);
// Navigate to the Email Verification screen
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EmailVerificationScreen(
email: email,
userId: widget.userId, // Pass user ID to the next screen
otp: otp,
otpId: otpId,
sendVerificationCode: sendVerificationCode,
),
),
context.go(
'/mailverification',
extra: {
'email': email,
'userId': widget.userId, // Pass user ID to the next screen
'otp': otp,
'otpId': otpId,
'sendVerificationCode': sendVerificationCode,
},
);
} else {
final error =
@ -132,6 +130,12 @@ class _ResetPasswordScreenState extends State<Changepassword> {
}
}
@override
void initState() {
super.initState();
print(widget.userId);
}
@override
void dispose() {
_emailController.dispose();

View File

@ -156,8 +156,8 @@ class _ConfirmPasswordState extends State<ConfirmPassword> {
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility
: Icons.visibility_off,
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
),
onPressed: () {
@ -184,8 +184,8 @@ class _ConfirmPasswordState extends State<ConfirmPassword> {
suffixIcon: IconButton(
icon: Icon(
_obscureConfirmPassword
? Icons.visibility
: Icons.visibility_off,
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
),
onPressed: () {

View File

@ -38,13 +38,50 @@ class _CreateNewPwState extends State<CreateNewPw> {
}
String? _validateNewPassword(String? value) {
// Define the regular expression for allowed characters
final regex = RegExp(
r'^[A-Za-z0-9~!@#$%^&*()_+=[\]{}|;:,.<>?/-àèìòùáéíóúÀÈÌÒÙÁÉÍÓÚ]*$');
// Define regular expressions for password complexity requirements
final hasUppercase = RegExp(r'[A-Z]');
final hasLowercase = RegExp(r'[a-z]');
final hasDigit = RegExp(r'\d');
final hasSpecialCharacter = RegExp(r'[~!@#$%^&*()_+=[\]{}|;:,.<>?/-]');
if (value == null || value.isEmpty) {
return 'New password is required';
} else if (value.length < 6) {
return 'Password must be at least 6 characters';
} else if (value.length < 8 || value.length > 64) {
return 'Password must be between 8 and 64 characters';
} else if (value == _oldPassword) {
return 'New password must not be the same as the old password';
}
// Check the regular expression for allowed characters
if (!regex.hasMatch(value)) {
return 'Password contains invalid characters';
}
// Track missing constraints
List<String> missingConstraints = [];
if (!hasUppercase.hasMatch(value)) {
missingConstraints.add('uppercase letter');
}
if (!hasLowercase.hasMatch(value)) {
missingConstraints.add('lowercase letter');
}
if (!hasDigit.hasMatch(value)) {
missingConstraints.add('numeric digit');
}
if (!hasSpecialCharacter.hasMatch(value)) {
missingConstraints.add('special character');
}
// If there are missing constraints, return a consolidated message
if (missingConstraints.isNotEmpty) {
return 'At least one ${missingConstraints.join(', ')}';
}
_newPassword = value; // Store for validation
return null;
}
@ -184,8 +221,8 @@ class _CreateNewPwState extends State<CreateNewPw> {
suffixIcon: IconButton(
icon: Icon(
_obscureOldPassword
? Icons.visibility
: Icons.visibility_off,
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
),
onPressed: () {
@ -208,8 +245,8 @@ class _CreateNewPwState extends State<CreateNewPw> {
suffixIcon: IconButton(
icon: Icon(
_obscureNewPassword
? Icons.visibility
: Icons.visibility_off,
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
),
onPressed: () {
@ -231,8 +268,8 @@ class _CreateNewPwState extends State<CreateNewPw> {
suffixIcon: IconButton(
icon: Icon(
_obscureConfirmPassword
? Icons.visibility
: Icons.visibility_off,
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
),
onPressed: () {

View File

@ -582,8 +582,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
fontSize: 16, color: Colors.white),
),
SizedBox(width: 8),
Icon(Icons.arrow_forward_ios,
color: Colors.white,size: 16,),
Icon(Icons.arrow_forward,
color: Colors.white),
],
),
),
@ -599,7 +599,6 @@ class _RegisterScreenState extends State<RegisterScreen> {
width: screenwidth / 1.3,
child: ElevatedButton(
onPressed: () {
context.go('/login');
// Add your login logic here
},
style: ElevatedButton.styleFrom(
@ -626,20 +625,31 @@ class _RegisterScreenState extends State<RegisterScreen> {
// ],
// ),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Login",
style: TextStyle(
fontSize: 16,
color: Colors.white,
child: GestureDetector(
onTap: () {
// Navigate to LoginRoute
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoginRoute()),
// MaterialPageRoute(builder: (context) => LoginRoute(userId: userID)),
);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Login",
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
),
SizedBox(width: 8),
Icon(Icons.arrow_forward_ios,
color: Colors.white,size: 16,),
],
SizedBox(width: 8),
Icon(Icons.arrow_forward,
color: Colors.white),
],
),
),
),
),

View File

@ -53,6 +53,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
final TextEditingController _emailController = TextEditingController();
// To keep track of the selected date
DateTime? _selectedDate;
String? role;
// Date format for the display
final DateFormat _dateFormat = DateFormat('yyyy-MM-dd');
@ -148,6 +149,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
setState(() {
_usernameController.text = userDetailsResponse.data['username'] ?? '';
_emailController.text = userDetailsResponse.data['email'] ?? '';
role = userDetailsResponse.data['role'] ?? '';
});
} catch (e) {
print('Error fetching user details: $e');
@ -271,7 +273,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
_resetFormFields();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Profile updated successfully!")));
context.go('/myhomepage');
if (role == 'admin') {
context.go('/manageuser');
} else {
context.go('/myhomepage');
}
} catch (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Failed to update profile: $error")));
@ -306,7 +312,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.black),
onPressed: () {
context.go('/myhomepage');
context.go('/');
},
),
title: Text(
@ -315,7 +321,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
actions: [
TextButton(
onPressed: () {},
onPressed: () {
context.go('/');
},
child: Text(
'Logout',
style: TextStyle(color: Colors.orange),
@ -425,8 +433,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
//RegExp(r"^[a-zA-Z\s]+$");
final nameRegex =
RegExp(r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF]+$");
final nameRegex = RegExp(
r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF\s]+$");
if (!nameRegex.hasMatch(value)) {
return 'Invalid Characters';
}
@ -698,7 +707,7 @@ class ConfirmationDialog extends StatelessWidget {
),
children: [
TextSpan(
text: "name",
text: "Name",
style:
TextStyle(fontWeight: FontWeight.w700), // Bold for "name"
),
@ -706,7 +715,7 @@ class ConfirmationDialog extends StatelessWidget {
text: " or ",
),
TextSpan(
text: "date of birth",
text: "Date of birth",
style: TextStyle(
fontWeight: FontWeight.w700), // Bold for "date of birth"
),

View File

@ -1,4 +1,3 @@
import 'package:external_repos/external_repos.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -38,8 +37,8 @@ class ThemedFormField extends HookWidget {
onPressed: () => isObscured.value = !isObscured.value,
icon: Icon(
isObscured.value
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
? Icons.visibility_off_outlined
: Icons.visibility_outlined,
color: const Color(0xff9EA2A9),
),
);

View File

@ -740,205 +740,206 @@ class _LoginRouteState extends State<LoginRoute> {
),
),
);
// final form = Form(
// key: formKey,
// child: Column(
// children: [
// ThemedFormField(
// hintText: context.translate(
// 'Email',
// 'بريد إلكتروني',
// ),
// validator: FieldValidator.email(),
// imgPath: MiscIconAssetPath.person,
// controller: emailCtl,
// ),
// 15.verticalSpace,
// ThemedFormField(
// validator: (text) {
// if (text!.length < 8) {
// return 'The password must be at least 8 characters';
// }
// return FieldValidator.password(minLength: 8)(text);
// },
// hintText: context.translate(
// 'Password',
// 'كلمة المرور',
// ),
// imgPath: MiscIconAssetPath.lock,
// controller: pwCtl,
// isObscurable: true,
// ),
// // 6.verticalSpace,
// Align(
// alignment: AlignmentDirectional.topEnd,
// child: forgotPwBtn,
// ),
// 10.verticalSpace,
// loginBtn,
// ],
// ),
// );
// final helloAndPleaseLoginTexts = Column(
// children: [
// Text(
// context.translate(
// 'Hello Again!',
// 'مرحبا مجددا!',
// ),
// style: TextStyle(
// fontFamily: context.translate(
// 'Roboto',
// 'NotoKufi',
// ),
// fontSize: 40,
// fontWeight: FontWeight.w300,
// ),
// ),
// 10.verticalSpace,
// Text(
// context.translate(
// 'Please login to access UAEs key official statistics',
// 'يرجى تسجيل الدخول للوصول إلى الإحصاءات الرسمية الرئيسية لدولة الإمارات العربية المتحدة',
// ),
// textAlign: TextAlign.center,
// style: TextStyle(
// fontFamily: context.translate(
// 'Roboto',
// 'NotoKufi',
// ),
// fontSize: 18,
// color: const Color(0xff898C81),
// fontWeight: FontWeight.w700,
// ),
// ),
// ],
// );
// final dontHaveAnAccountRegisterBtn = TextButton(
// onPressed: () => {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => RegisterScreen()),
// ),
// },
// child: Text.rich(
// textAlign: TextAlign.center,
// TextSpan(
// style: TextStyle(
// fontFamily: context.translate(
// 'Roboto',
// 'NotoKufi',
// ),
// fontSize: 18,
// fontWeight: FontWeight.bold,
// ),
// children: [
// TextSpan(
// text: context.translate(
// 'Don\'t have an account? ',
// 'ليس لديك حساب؟',
// ),
// style: const TextStyle(
// color: Color(0xff898C81),
// ),
// ),
// const TextSpan(
// text: ' ',
// ),
// TextSpan(
// text: context.translate(
// 'Register Now',
// 'سجل الان',
// ),
// style: TextStyle(
// color: MyTheme.topicColor(IndicatorTopic.economy).shade600,
// ),
// ),
// ],
// ),
// ),
// );
// final continueAsGuestBtn = SizedBox(
// width: double.infinity,
// child: ElevatedButton(
// onPressed: () => context
// .go('/${context.language}/${BottomNavBarItem.home.routePath}'),
// style: ButtonStyle(
// shape: WidgetStatePropertyAll(
// RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(10),
// ),
// ),
// padding: const WidgetStatePropertyAll(
// EdgeInsets.symmetric(vertical: 10.5),
// ),
// textStyle: WidgetStatePropertyAll(
// TextStyle(
// fontFamily: context.translate(
// 'Roboto',
// 'NotoKufi',
// ),
// fontSize: 16,
// fontWeight: FontWeight.w600,
// ),
// ),
// backgroundColor: WidgetStatePropertyAll(
// MyTheme.topicColor(IndicatorTopic.environment),
// ),
// foregroundColor: const WidgetStatePropertyAll(
// Colors.white,
// ),
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// context.translate(
// 'Continue as Guest',
// 'استمر كضيف',
// ),
// ),
// 6.horizontalSpace,
// const Icon(Icons.chevron_right_outlined),
// ],
// ),
// ),
// );
// final fcscBanner = Image.asset(
// BannerAssetPath.fcsc,
// height: 56,
// );
// final screenWidth = MediaQuery.of(context).size.width;
// final listViewHorizontalPadding =
// screenWidth < 700 ? 30 : 30 + (screenWidth - 700) / 2;
// final scaffoldBody = ListView(
// padding: EdgeInsets.symmetric(
// horizontal: listViewHorizontalPadding.toDouble(),
// ),
// children: [
// 36.verticalSpace,
// const Align(
// alignment: AlignmentDirectional.topEnd,
// child: LangToggle(),
// ),
// 16.verticalSpace,
// helloAndPleaseLoginTexts,
// 42.verticalSpace,
// form,
// 20.verticalSpace,
// dontHaveAnAccountRegisterBtn,
// 36.verticalSpace,
// continueAsGuestBtn,
// 72.verticalSpace,
// fcscBanner,
// ],
// );
// final bgScaffold = Scaffold(
// backgroundColor: Colors.white,
// body: SafeArea(child: scaffoldBody),
// );
// return bgScaffold;
// >>>>>>> b0c5ebce3deb7da2aa24b0ea5ffe684df7dfb7bf
<<<<<<< HEAD
=======
final form = Form(
key: formKey,
child: Column(
children: [
ThemedFormField(
hintText: context.translate(
'Email',
'بريد إلكتروني',
),
validator: FieldValidator.email(),
imgPath: MiscIconAssetPath.person,
controller: emailCtl,
),
15.verticalSpace,
ThemedFormField(
validator: (text) {
if (text!.length < 8) {
return 'The password must be at least 8 characters';
}
return FieldValidator.password(minLength: 8)(text);
},
hintText: context.translate(
'Password',
'كلمة المرور',
),
imgPath: MiscIconAssetPath.lock,
controller: pwCtl,
isObscurable: true,
),
// 6.verticalSpace,
Align(
alignment: AlignmentDirectional.topEnd,
child: forgotPwBtn,
),
10.verticalSpace,
loginBtn,
],
),
);
final helloAndPleaseLoginTexts = Column(
children: [
Text(
context.translate(
'Hello Again!',
'مرحبا مجددا!',
),
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 40,
fontWeight: FontWeight.w300,
),
),
10.verticalSpace,
Text(
context.translate(
'Please login to access UAEs key official statistics',
'يرجى تسجيل الدخول للوصول إلى الإحصاءات الرسمية الرئيسية لدولة الإمارات العربية المتحدة',
),
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 18,
color: const Color(0xff898C81),
fontWeight: FontWeight.w700,
),
),
],
);
final dontHaveAnAccountRegisterBtn = TextButton(
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => RegisterScreen()),
),
},
child: Text.rich(
textAlign: TextAlign.center,
TextSpan(
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 18,
fontWeight: FontWeight.bold,
),
children: [
TextSpan(
text: context.translate(
'Don\'t have an account? ',
'ليس لديك حساب؟',
),
style: const TextStyle(
color: Color(0xff898C81),
),
),
const TextSpan(
text: ' ',
),
TextSpan(
text: context.translate(
'Register Now',
'سجل الان',
),
style: TextStyle(
color: MyTheme.topicColor(IndicatorTopic.economy).shade600,
),
),
],
),
),
);
final continueAsGuestBtn = SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => context
.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
style: ButtonStyle(
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
padding: const WidgetStatePropertyAll(
EdgeInsets.symmetric(vertical: 10.5),
),
textStyle: WidgetStatePropertyAll(
TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
backgroundColor: WidgetStatePropertyAll(
MyTheme.topicColor(IndicatorTopic.environment),
),
foregroundColor: const WidgetStatePropertyAll(
Colors.white,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.translate(
'Continue as Guest',
'استمر كضيف',
),
),
6.horizontalSpace,
const Icon(Icons.chevron_right_outlined),
],
),
),
);
final fcscBanner = Image.asset(
BannerAssetPath.fcsc,
height: 56,
);
final screenWidth = MediaQuery.of(context).size.width;
final listViewHorizontalPadding =
screenWidth < 700 ? 30 : 30 + (screenWidth - 700) / 2;
final scaffoldBody = ListView(
padding: EdgeInsets.symmetric(
horizontal: listViewHorizontalPadding.toDouble(),
),
children: [
36.verticalSpace,
const Align(
alignment: AlignmentDirectional.topEnd,
child: LangToggle(),
),
16.verticalSpace,
helloAndPleaseLoginTexts,
42.verticalSpace,
form,
20.verticalSpace,
dontHaveAnAccountRegisterBtn,
36.verticalSpace,
continueAsGuestBtn,
72.verticalSpace,
fcscBanner,
],
);
final bgScaffold = Scaffold(
backgroundColor: Colors.white,
body: SafeArea(child: scaffoldBody),
);
return bgScaffold;
>>>>>>> b0c5ebce3deb7da2aa24b0ea5ffe684df7dfb7bf
}
}

View File

@ -262,72 +262,72 @@ class _EditProfileState extends State<EditProfile> {
}
void showConfirmationDialog(BuildContext context) async {
final result = await showDialog<bool>(
context: context,
builder: (context) => const ConfirmationDialog(),
);
// final result = await showDialog<bool>(
// context: context,
// builder: (context) => const ConfirmationDialog(),
// );
if (result == true) {
// Validate only the country field
if (_validateDropdown(_selectedCountry) == null) {
try {
String userID = userId;
// if (result == true) {
// Validate only the country field
if (_validateDropdown(_selectedCountry) == null) {
try {
String userID = userId;
print("ShowConfirmationuserID - $userID ");
// Retrieve data from the country/region field
String countryRegion =
_selectedCountry ?? ''; // Ensure the country is selected
print("ShowConfirmationuserID - $userID ");
// Retrieve data from the country/region field
String countryRegion =
_selectedCountry ?? ''; // Ensure the country is selected
// Create a multipart request
final uri =
Uri.parse('${_pb.baseUrl}/api/collections/users/records/$userID');
final request = http.MultipartRequest('PATCH', uri);
// Create a multipart request
final uri =
Uri.parse('${_pb.baseUrl}/api/collections/users/records/$userID');
final request = http.MultipartRequest('PATCH', uri);
// Add fields to the request
request.fields['country_region'] =
countryRegion; // Only update country here
// Add fields to the request
request.fields['country_region'] =
countryRegion; // Only update country here
// If profile image exists, add it
if (_profileImage != null) {
request.files.add(await http.MultipartFile.fromPath(
'avatar',
_profileImage!.path,
));
}
// If profile image exists, add it
if (_profileImage != null) {
request.files.add(await http.MultipartFile.fromPath(
'avatar',
_profileImage!.path,
));
}
// Add headers (e.g., authorization)
request.headers['Authorization'] = 'Bearer ${_pb.authStore.token}';
// Add headers (e.g., authorization)
request.headers['Authorization'] = 'Bearer ${_pb.authStore.token}';
// Send the request
final response = await request.send();
print(response);
// Send the request
final response = await request.send();
print(response);
// Handle response
if (response.statusCode == 200) {
_resetFormFields();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Profile updated successfully!")),
);
context.go('/myhomepage');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("Failed to update profile: ${response.statusCode}")),
);
}
} catch (error) {
// Handle response
if (response.statusCode == 200) {
_resetFormFields();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Failed to update profile: $error")),
SnackBar(content: Text("Profile updated successfully!")),
);
context.go('/myhomepage');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("Failed to update profile: ${response.statusCode}")),
);
}
} else {
// Show an error if the country is invalid
setState(() {
showError = true;
});
} catch (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Failed to update profile: $error")),
);
}
} else {
// Show an error if the country is invalid
setState(() {
showError = true;
});
}
// }
}
void _resetFormFields() {
@ -462,7 +462,7 @@ class _EditProfileState extends State<EditProfile> {
//RegExp(r"^[a-zA-Z\s]+$");
final nameRegex = RegExp(
r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF]+$");
r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF\s]+$");
if (!nameRegex.hasMatch(value)) {
return 'Invalid Characters';
}

View File

@ -43,9 +43,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
try {
await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final result = await _pb.collection('users').getFullList(
filter: 'verified = false',
);
final result = await _pb.collection('users').getFullList();
setState(() {
userData = result.map((record) {
@ -178,6 +176,8 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
user.id, // User's unique ID
body: {
'status': newStatus, // Update status
'verified': newStatus == 'Approved' ? true : false,
'reviewed': true,
},
);

View File

@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:share_plus/share_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
class BaseScaffold extends StatelessWidget {
class BaseScaffold extends StatefulWidget {
final Widget body;
final Widget title;
final List<Widget>? actions;
@ -12,9 +15,81 @@ class BaseScaffold extends StatelessWidget {
required this.title,
this.actions,
}) : super(key: key);
// final Widget body;
//
// const BaseScaffold({required this.body});
@override
_BaseScaffoldState createState() => _BaseScaffoldState();
}
class _BaseScaffoldState extends State<BaseScaffold> {
final _pb = PocketBase('https://pb.venbait.in');
String _avatarUrl = '';
dynamic userId;
String? userName;
String? userEmail;
String? userAvatar;
String? role;
@override
void initState() {
super.initState();
_checkUserId();
}
// Method to retrieve userId from SharedPreferences
Future<String?> getUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('userId'); // Retrieve the userId
}
// Method to check if userId exists and update state
Future<void> _checkUserId() async {
String? fetchedUserId = await getUserId();
if (fetchedUserId != null && fetchedUserId.isNotEmpty) {
setState(() {
userId = fetchedUserId;
});
//print('NAVUser ID: $userId');
_fetchUserData();
} else {
print('No userId found');
// Handle the case where userId is not available
}
}
Future<void> _fetchUserData() async {
try {
final adminAuth = await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final adminToken = adminAuth.token;
//print('adminToken- ${adminToken}');
final userDetailsResponse = await _pb.collection('users').getOne(
userId!,
headers: {
'Authorization': 'Bearer $adminToken',
},
);
print('NAVuserDetails: $userDetailsResponse');
setState(() {
userName = userDetailsResponse.data['username'] ?? '';
userEmail = userDetailsResponse.data['email'] ?? '';
userAvatar = userDetailsResponse.data['avatar'] ?? '';
role = userDetailsResponse.data['role'] ?? '';
String recordId = userId;
String collectionId =
userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_';
if (userAvatar!.isNotEmpty && recordId.isNotEmpty) {
_avatarUrl =
'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar';
} else {
_avatarUrl = ''; // Reset to default or empty
}
});
} catch (e) {
print('Error fetching user details: $e');
}
}
@override
Widget build(BuildContext context) {
@ -22,15 +97,29 @@ class BaseScaffold extends StatelessWidget {
String currentRoute = GoRouterState.of(context).matchedLocation;
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(title: title, actions: [
IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
]),
appBar: AppBar(
title: widget.title,
actions: [
// IconButton(
// onPressed: () {
// // Share logic here
// print("Share icon pressed");
// Share.share(
// 'Open the app: fcscapp://home\n\n'
// 'If you dont have the app installed, '
// 'visit: http://localhost:65493');
// },
// icon: Icon(Icons.share),
// ),
IconButton(onPressed: () {}, icon: Icon(Icons.toggle_off_outlined)),
],
),
drawer: Drawer(
child: ListView(
children: [
DrawerHeader(
//decoration: BoxDecoration(color: Colors.blue),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
@ -48,18 +137,39 @@ class BaseScaffold extends StatelessWidget {
child: Row(
children: [
SizedBox(
width: mywidth / 8,
child: Image(
image: AssetImage(
'assets/edit_profile/profile.png'))),
width: mywidth / 8,
height: mywidth / 8,
child: ClipOval(
child: _avatarUrl.isNotEmpty
? Image(
image: NetworkImage(_avatarUrl),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
)
: Image(
image: AssetImage(
'assets/edit_profile/profile.png'),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
),
//child: Image(image: AssetImage('assets/edit_profile/profile.png'))
),
SizedBox(
width: mywidth / 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Mohammad'),
Text('Mohammad@fcsc.com')
// Text(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),
],
)
],
@ -68,24 +178,27 @@ class BaseScaffold extends StatelessWidget {
],
),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/message.png'))),
title: Text('Feedback'),
onTap: () => context.go('/feedback'),
),
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/manageuser.png'))),
title: Text('Manage User'),
onTap: () => context.go('/manageuser'),
),
if (role != 'admin')
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image: AssetImage('assets/icons/drawer/message.png'))),
title: Text('Feedback'),
onTap: () => context.go('/feedback'),
),
if (role == 'admin')
ListTile(
leading: SizedBox(
height: myheight / 15,
width: mywidth / 15,
child: Image(
image:
AssetImage('assets/icons/drawer/manageuser.png'))),
title: Text('Manage User'),
onTap: () => context.go('/manageuser'),
),
],
),
),
@ -130,11 +243,11 @@ class BaseScaffold extends StatelessWidget {
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
),
body: body,
body: widget.body,
);
}
//Map the current route to the selected index
// Map the current route to the selected index
int _getSelectedIndex(String route) {
switch (route) {
case '/myhomepage':
@ -150,7 +263,7 @@ class BaseScaffold extends StatelessWidget {
}
}
//Handle navigation when an item is tapped
// Handle navigation when an item is tapped
void _onItemTapped(BuildContext context, int index) {
switch (index) {
case 0:

View File

@ -27,7 +27,7 @@ class ResetPwRoute extends HookConsumerWidget {
suffixIcon: IconButton(
onPressed: () => doObscureOld.value = !doObscureOld.value,
icon: Icon(
doObscureOld.value ? Icons.visibility : Icons.visibility_off,
doObscureOld.value ? Icons.visibility_off : Icons.visibility,
),
),
),
@ -51,7 +51,7 @@ class ResetPwRoute extends HookConsumerWidget {
suffixIcon: IconButton(
onPressed: () => doObscureNew.value = !doObscureNew.value,
icon: Icon(
doObscureNew.value ? Icons.visibility : Icons.visibility_off,
doObscureNew.value ? Icons.visibility_off : Icons.visibility,
),
),
),
@ -72,7 +72,7 @@ class ResetPwRoute extends HookConsumerWidget {
onPressed: () =>
doObscureConfirmNew.value = !doObscureConfirmNew.value,
icon: Icon(
doObscureConfirmNew.value ? Icons.visibility : Icons.visibility_off,
doObscureConfirmNew.value ? Icons.visibility_off : Icons.visibility,
),
),
),

View File

@ -1244,6 +1244,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
syncfusion_flutter_charts:
dependency: "direct main"
description:
name: syncfusion_flutter_charts
sha256: b2a9f0fd585ef96c081c37697b46d48d3b0f3fe6bddc5011a3542962814fafa8
url: "https://pub.dev"
source: hosted
version: "28.1.33"
syncfusion_flutter_core:
dependency: transitive
description:
name: syncfusion_flutter_core
sha256: b1071c698b502e7d55f91352a8b82d42f49f4c96e523d43b6fade5d5af710048
url: "https://pub.dev"
source: hosted
version: "28.1.33"
term_glyph:
dependency: transitive
description:

View File

@ -54,6 +54,7 @@ dependencies:
provider: ^6.1.2
mailer: ^6.2.0
image_picker: ^1.1.2
syncfusion_flutter_charts: ^28.1.33
dependency_overrides:
fading_edge_scrollview: ^4.1.1