notification bug fix

This commit is contained in:
venbaittech 2025-03-06 18:51:53 +05:30
parent b5d0b38ac7
commit 44c21defa7
8 changed files with 529 additions and 307 deletions

View File

@ -22,7 +22,7 @@ class LoadingOverlay {
color: Colors.black.withOpacity(0.5), dismissible: false),
Center(
child: Image.asset(
"assets/images/loading.gif", // Make sure to add the GIF in assets
"assets/FCSC-GIF.gif", // Make sure to add the GIF in assets
width: 100,
height: 100,
),

View File

@ -364,302 +364,305 @@ final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
// }
final GoRouter router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
//builder: (context, state) => MyHomePage(),
builder: (context, state) => SessionCheckScreen(),
),
// GoRoute(
// path: '/',
// redirect: (context, state) async => await _checkSession(),
// ),
GoRoute(
path: '/internetcheck',
builder: (context, state) => InternetCheck(),
),
GoRoute(
path: '/login',
builder: (context, state) => LoginRoute(),
//builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/myhomepage',
builder: (context, state) => MyHomePage(),
),
GoRoute(
path: '/register',
builder: (context, state) => RegisterScreen(),
),
// GoRoute(
// path: '/DemoHome/:dataSets',
// builder: (context, state) {
// final dataSets = state.pathParameters['dataSets']!;
// print('Router $dataSets');
// return ChartPage(dataSets: dataSets);
// },
// ),
// GoRoute(
// path: '/Chart/:dataSets',
// builder: (context, state) {
// final dataSets = state.pathParameters['dataSets']!;
// print('Router $dataSets');
// return ChartScreen(dataSets: dataSets);
// },
// ),
GoRoute(
path: '/chartScreen/:dataSets',
builder: (context, state) {
// Retrieve path parameter
final dataSets = state.pathParameters['dataSets']!;
// Retrieve query parameter
final bgColor = state.uri.queryParameters['bgColor'] ??
'0xFFFFFFFF'; // Default white
final mainTopic = state.uri.queryParameters['mainTopic'] ?? '';
final title = state.uri.queryParameters['title'] ?? '';
final key = state.uri.queryParameters['key'] ?? '';
final kpi = state.uri.queryParameters['kpi'] ?? ''; // Get kpi
initialLocation: '/',
routes: [
GoRoute(
path: '/',
//builder: (context, state) => MyHomePage(),
builder: (context, state) => SessionCheckScreen(),
),
// GoRoute(
// path: '/',
// redirect: (context, state) async => await _checkSession(),
// ),
GoRoute(
path: '/internetcheck',
builder: (context, state) => InternetCheck(),
),
GoRoute(
path: '/login',
builder: (context, state) => LoginRoute(),
//builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/myhomepage',
builder: (context, state) => MyHomePage(),
),
GoRoute(
path: '/register',
builder: (context, state) => RegisterScreen(),
),
// GoRoute(
// path: '/DemoHome/:dataSets',
// builder: (context, state) {
// final dataSets = state.pathParameters['dataSets']!;
// print('Router $dataSets');
// return ChartPage(dataSets: dataSets);
// },
// ),
// GoRoute(
// path: '/Chart/:dataSets',
// builder: (context, state) {
// final dataSets = state.pathParameters['dataSets']!;
// print('Router $dataSets');
// return ChartScreen(dataSets: dataSets);
// },
// ),
GoRoute(
path: '/chartScreen/:dataSets',
builder: (context, state) {
// Retrieve path parameter
final dataSets = state.pathParameters['dataSets']!;
// Retrieve query parameter
final bgColor = state.uri.queryParameters['bgColor'] ??
'0xFFFFFFFF'; // Default white
final mainTopic = state.uri.queryParameters['mainTopic'] ?? '';
final title = state.uri.queryParameters['title'] ?? '';
final key = state.uri.queryParameters['key'] ?? '';
final kpi = state.uri.queryParameters['kpi'] ?? ''; // Get kpi
// Parse filter_data as a JSON list
// Parse filter_data as a JSON list
List<Map<String, dynamic>> filterData = [];
// Parse filter_data as a JSON list
// Parse filter_data as a JSON list
List<Map<String, dynamic>> filterData = [];
if (state.uri.queryParameters.containsKey('filter_data') &&
state.uri.queryParameters['filter_data']!.isNotEmpty) {
try {
filterData = List<Map<String, dynamic>>.from(
jsonDecode(state.uri.queryParameters['filter_data']!));
} catch (e) {
print('Error parsing filter_data: $e');
filterData = []; // Assign an empty list to prevent null issues
if (state.uri.queryParameters.containsKey('filter_data') &&
state.uri.queryParameters['filter_data']!.isNotEmpty) {
try {
filterData = List<Map<String, dynamic>>.from(
jsonDecode(state.uri.queryParameters['filter_data']!));
} catch (e) {
print('Error parsing filter_data: $e');
filterData = []; // Assign an empty list to prevent null issues
}
} else {
filterData = []; // Ensure it's a valid list
}
} else {
filterData = []; // Ensure it's a valid list
}
print('Router dataSets: $dataSets');
print('Router bgColor: $bgColor');
print('Router mainTopic: $mainTopic');
print('Router title: $title');
print('Router filter: $filterData');
print('Router dataSets: $dataSets');
print('Router bgColor: $bgColor');
print('Router mainTopic: $mainTopic');
print('Router title: $title');
print('Router filter: $filterData');
// Pass both values to the screen
return ChartScreen1(
dataSets: dataSets,
bgColor: bgColor,
mainTopic: mainTopic,
title: title,
keyParam: key,
kpi: kpi,
filter_data: filterData,
);
},
),
GoRoute(
path: '/mailverification',
builder: (context, state) => EmailVerificationScreen(
email: '',
userId: '',
otp: '',
otpId: '',
sendVerificationCode: (String) {},
// Pass both values to the screen
return ChartScreen1(
dataSets: dataSets,
bgColor: bgColor,
mainTopic: mainTopic,
title: title,
keyParam: key,
kpi: kpi,
filter_data: filterData,
);
},
),
),
GoRoute(
path: '/changepassword/:userId',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
return Changepassword(userId: userId);
},
),
GoRoute(
path: '/createNewPw/:userId/:email',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
final email = state.pathParameters['email']!;
final key = state.uri.queryParameters['key'] ?? '';
return CreateNewPw(userId: userId, email: email, keyParam: key);
},
),
GoRoute(
path: '/confirmpasswd',
builder: (context, state) => ConfirmPassword(
email: '',
userId: '',
GoRoute(
path: '/mailverification',
builder: (context, state) => EmailVerificationScreen(
email: '',
userId: '',
otp: '',
otpId: '',
sendVerificationCode: (String) {},
),
),
GoRoute(
path: '/changepassword/:userId',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
return Changepassword(userId: userId);
},
),
GoRoute(
path: '/createNewPw/:userId/:email',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
final email = state.pathParameters['email']!;
final key = state.uri.queryParameters['key'] ?? '';
return CreateNewPw(userId: userId, email: email, keyParam: key);
},
),
GoRoute(
path: '/confirmpasswd',
builder: (context, state) => ConfirmPassword(
email: '',
userId: '',
),
),
GoRoute(
path: '/terms&conditions',
builder: (context, state) => TermsOfUse(),
//builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/privacy_policy',
builder: (context, state) => PrivacyPolicy(),
//builder: (context, state) => LoginRoute(),
),
),
GoRoute(
path: '/terms&conditions',
builder: (context, state) => TermsOfUse(),
//builder: (context, state) => LoginRoute(),
),
GoRoute(
path: '/privacy_policy',
builder: (context, state) => PrivacyPolicy(),
//builder: (context, state) => LoginRoute(),
),
// Drawer Routers
GoRoute(
path: '/feedback',
builder: (context, state) => FeedbackForm(),
),
//Sub route
GoRoute(
path: '/profile/:userId',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
return ProfileScreen(userId: userId);
},
),
GoRoute(
path: '/notification',
builder: (context, state) {
// final userId = state.pathParameters['userId']!;
return NotificationPage();
},
),
GoRoute(
path: '/notification_details',
builder: (context, state) {
final Map<String, dynamic> data = state.extra as Map<String, dynamic>;
return NotificationDetails(
title: data['title'] ?? '',
message: data['message'] ?? '',
date: data['date'] ?? '',
category: data['category'] ?? '',
);
},
),
GoRoute(
path: '/user-guide',
builder: (context, state) => Userguide(),
routes: <RouteBase>[
GoRoute(
path: '/features',
name: 'features',
builder: (context, state) => UsingFeatures(),
routes: <RouteBase>[
GoRoute(
path: 'whoUseApp',
name: 'whoUseApp',
builder: (context, state) => WhoUseTheApp(),
),
GoRoute(
path: 'howUseApp',
name: 'howUseApp',
builder: (context, state) => HowUseTheApp(),
),
GoRoute(
path: 'purpose',
name: 'purpose',
builder: (context, state) => Purpose(),
),
GoRoute(
path: 'stayUpdated',
name: 'stayUpdated',
builder: (context, state) => StayUpdate(),
),
GoRoute(
path: 'changeMyPassword',
name: 'changeMyPassword',
builder: (context, state) => ChangeMyPassword(),
),
GoRoute(
path: 'appFeatures',
name: 'appFeatures',
builder: (context, state) => AppFeatures(),
),
GoRoute(
path: 'editMyProfile',
name: 'editMyProfile',
builder: (context, state) => EditMyProfile(),
),
],
),
GoRoute(
path: 'aboutApp',
builder: (context, state) => aboutTheApp(),
GoRoute(
path: '/feedback',
builder: (context, state) => FeedbackForm(),
),
//Sub route
GoRoute(
path: '/profile/:userId',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
return ProfileScreen(userId: userId);
},
),
GoRoute(
path: '/notification',
builder: (context, state) {
// final userId = state.pathParameters['userId']!;
return NotificationPage();
},
),
GoRoute(
path: '/notification_details',
builder: (context, state) {
final Map<String, dynamic> data = state.extra as Map<String, dynamic>;
return NotificationDetails(
title: data['title'] ?? '',
message: data['message'] ?? '',
date: data['date'] ?? '',
category: data['category'] ?? '',
id: data['id'] ?? '',
backNavigation: data['backNavigation'] ?? '',
);
},
),
GoRoute(
path: '/user-guide',
builder: (context, state) => Userguide(),
routes: <RouteBase>[
GoRoute(
path: '/features',
name: 'features',
builder: (context, state) => UsingFeatures(),
routes: <RouteBase>[
GoRoute(
path: 'aboutFCSC',
name: 'aboutFCSC',
builder: (context, state) => aboutFCSC(),
path: 'whoUseApp',
name: 'whoUseApp',
builder: (context, state) => WhoUseTheApp(),
),
GoRoute(
path: 'getStarted',
name: 'getStarted',
builder: (context, state) => GetStarted(),
path: 'howUseApp',
name: 'howUseApp',
builder: (context, state) => HowUseTheApp(),
),
]),
GoRoute(
path: '/faq',
name: 'faq',
builder: (context, state) => FAQPage(),
),
],
),
// GoRoute(
// path: '/manageuser',
// builder: (context, state) {
// // Retrieve the title from extra or query params
// final title = state.extra as String? ?? 'Manage users';
// return ManageUserRouter(title: title);
// },
// ),
GoRoute(
path: '/editProfile',
builder: (context, state) => EditProfile(),
),
GoRoute(
path: '/bookmark',
builder: (context, state) => BookMark(),
),
GoRoute(
path: '/manageuser',
builder: (context, state) => ManageUserRouter(),
),
GoRoute(
path: 'purpose',
name: 'purpose',
builder: (context, state) => Purpose(),
),
GoRoute(
path: 'stayUpdated',
name: 'stayUpdated',
builder: (context, state) => StayUpdate(),
),
GoRoute(
path: 'changeMyPassword',
name: 'changeMyPassword',
builder: (context, state) => ChangeMyPassword(),
),
GoRoute(
path: 'appFeatures',
name: 'appFeatures',
builder: (context, state) => AppFeatures(),
),
GoRoute(
path: 'editMyProfile',
name: 'editMyProfile',
builder: (context, state) => EditMyProfile(),
),
],
),
GoRoute(
path: 'aboutApp',
builder: (context, state) => aboutTheApp(),
routes: <RouteBase>[
GoRoute(
path: 'aboutFCSC',
name: 'aboutFCSC',
builder: (context, state) => aboutFCSC(),
),
GoRoute(
path: 'getStarted',
name: 'getStarted',
builder: (context, state) => GetStarted(),
),
]),
GoRoute(
path: '/faq',
name: 'faq',
builder: (context, state) => FAQPage(),
),
],
),
// GoRoute(
// path: '/manageuser',
// builder: (context, state) {
// // Retrieve the title from extra or query params
// final title = state.extra as String? ?? 'Manage users';
// return ManageUserRouter(title: title);
// },
// ),
GoRoute(
path: '/editProfile',
builder: (context, state) => EditProfile(),
),
GoRoute(
path: '/bookmark',
builder: (context, state) => BookMark(),
),
GoRoute(
path: '/manageuser',
builder: (context, state) => ManageUserRouter(),
),
// Bottom Navigation Routes
// GoRoute(
// path: '/uaenumbers',
// builder: (context, state) => UaeNumbers(),
// ),
GoRoute(path: '/uaenumbers', builder: (context, state) => UaeNumbers()),
// Bottom Navigation Routes
// GoRoute(
// path: '/uaenumbers',
// builder: (context, state) => UaeNumbers(),
// ),
GoRoute(path: '/uaenumbers', builder: (context, state) => UaeNumbers()),
GoRoute(
path: '/competitiveness',
builder: (context, state) => Competitiveness(),
),
GoRoute(
path: '/competitiveness',
builder: (context, state) => Competitiveness(),
),
GoRoute(
path: '/countryprofile',
builder: (context, state) => CountryProfile(),
),
GoRoute(
path: '/countryprofile',
builder: (context, state) => CountryProfile(),
),
GoRoute(
path: '/marriages',
builder: (context, state) => Marriages(),
),
GoRoute(
path: '/marriages',
builder: (context, state) => Marriages(),
),
GoRoute(
path: '/contact',
builder: (context, state) => Contact(),
),
],
GoRoute(
path: '/contact',
builder: (context, state) => Contact(),
),
],
redirect: (context, state) async {
if (state.uri.path == '/SessionCheckScreen' || state.uri.path == '/login') {
if (state.uri.path == '/SessionCheckScreen' ||
state.uri.path == '/login') {
return null;
}
final session = await PAuthRepo().fetchLocallyStored();
if (session == null || session.freshness == SessionFreshness.expired) {
print('Session expired, redirecting to login with intendedPath: ${state.uri.path}');
print(
'Session expired, redirecting to login with intendedPath: ${state.uri.path}');
return '/login${state.uri.path != '/' ? '?intendedPath=${state.uri.path}' : ''}';
}
return null;
}
);
});

View File

@ -45,6 +45,13 @@
"account_confirmation": "هل لديك حساب؟ سجل الدخول",
"login_title": "تسجيل الدخول",
"all_updates": "جميع التحديثات",
"app_updates": "تحديثات التطبيق",
"notificationSocial": "اجتماعي",
"notificationEconomy": "اقتصاد",
"notificationEnvironment": "بيئة",
"notificationFavourites": "المفضلة",
"profile_title": "نموذج الملاحظات",
"my_profile": "ملفي الشخصي",
"logout": "تسجيل الخروج",

View File

@ -1,8 +1,8 @@
{
"all_bookmarks":"All Bookmarks",
"economy_title":"Economy",
"social_title":"Social",
"environment_title":"Environment",
"all_bookmarks": "All Bookmarks",
"economy_title": "Economy",
"social_title": "Social",
"environment_title": "Environment",
"bookmarks": "Bookmarks",
"feedback_title": "Feedback",
@ -41,7 +41,12 @@
"account_confirmation": "Already have an account?",
"login_title": "Login",
"all_updates": "All updates",
"app_updates": "App updates",
"notificationSocial": "Social",
"notificationEconomy": "Economy",
"notificationEnvironment": "Environment",
"notificationFavourites": "Favourites",
"profile_title": "Edit Profile",
"my_profile": "My Profile",

View File

@ -65,7 +65,19 @@ class _EditProfileState extends State<EditProfile> {
'India',
'Canada',
];
final List<String> preferred_language = ['English', 'Arabic'];
final Map<String, String> languageMap = {
"en": "English",
"ar": "Arabic",
};
// Reverse mapping for saving back to API
final Map<String, String> reverseLanguageMap = {
"English": "en",
"Arabic": "ar",
};
String? _selectedCountry;
String? _selectedLanguage;
bool isChecked = false;
bool showError = false;
final _picker = ImagePicker();
@ -82,6 +94,7 @@ class _EditProfileState extends State<EditProfile> {
dynamic role;
bool _isHoveringDropdown = false;
bool _isHoveringPreferredLang = false;
@override
void initState() {
@ -177,10 +190,16 @@ class _EditProfileState extends State<EditProfile> {
print('userDetails: $userDetailsResponse');
setState(() {
setState(() {
_selectedLanguage =
languageMap[userDetailsResponse.data['language']] ??
'English'; // Default to English if not found
});
_usernameController.text = userDetailsResponse.data['uname'] ?? '';
_emailController.text = userDetailsResponse.data['email'] ?? '';
_fullNameController.text = userDetailsResponse.data['full_name'] ?? '';
_selectedCountry = userDetailsResponse.data['country_region'] ?? '';
// _selectedLanguage = userDetailsResponse.data['language'] ?? '';
_isProfileCompleted =
userDetailsResponse.data['is_profile_completed'] ?? false;
//_isProfileCompleted = true ;
@ -321,6 +340,13 @@ class _EditProfileState extends State<EditProfile> {
return null;
}
String? _validatePreferredLang(String? value) {
if (value == null || value.isEmpty) {
return context.translate('Required', 'مطلوب');
}
return null;
}
void _toggleCheckbox(bool? value) {
setState(() {
isChecked = value ?? false;
@ -335,7 +361,8 @@ class _EditProfileState extends State<EditProfile> {
// if (result == true) {
// Validate only the country field
if (_validateDropdown(_selectedCountry) == null) {
if (_validateDropdown(_selectedCountry) == null &&
_validatePreferredLang(_selectedLanguage) == null) {
try {
String userID = userId;
@ -343,6 +370,7 @@ class _EditProfileState extends State<EditProfile> {
// Retrieve data from the country/region field
String countryRegion =
_selectedCountry ?? ''; // Ensure the country is selected
String preferredLang = _selectedLanguage ?? '';
// Create a multipart request
final uri =
@ -352,6 +380,7 @@ class _EditProfileState extends State<EditProfile> {
// Add fields to the request
request.fields['country_region'] =
countryRegion; // Only update country here
request.fields['language'] = preferredLang == 'English' ? 'en' : 'ar';
// If profile image exists, add it
if (_profileImage != null) {
@ -406,6 +435,7 @@ class _EditProfileState extends State<EditProfile> {
_fullNameController.clear();
_dateController.clear();
_selectedCountry = null;
_selectedLanguage = null;
isChecked = false;
// Reset profile image
@ -829,6 +859,73 @@ class _EditProfileState extends State<EditProfile> {
validator: _validateDropdown,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!
.preferredLang,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500),
),
],
),
SizedBox(height: 10),
MouseRegion(
onEnter: (_) => setState(
() => _isHoveringPreferredLang = true),
onExit: (_) => setState(
() => _isHoveringPreferredLang = false),
child: DropdownButtonFormField<String>(
style: TextStyle(
fontFamily: 'Roboto',
fontSize: 16,
fontWeight: FontWeight.normal,
color: Color(0xFF544C4C),
),
value: _selectedLanguage,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10),
borderSide: BorderSide(
color: MyTheme.topicColor(
IndicatorTopic.economy)
.shade400,
width: 1), // Enabled border
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFF7296BE),
),
borderRadius:
BorderRadius.circular(8),
),
labelText: 'Select',
),
icon: Icon(
Icons.keyboard_arrow_down_sharp,
color: _isHoveringPreferredLang
? Colors.black
: Colors.grey),
items: preferred_language
.map(
(item) => DropdownMenuItem<String>(
value: item,
child: Text(item),
),
)
.toList(),
onChanged: (String? newValue) {
setState(() {
_selectedLanguage = newValue;
});
},
validator: _validatePreferredLang,
),
),
SizedBox(height: 20),
if (!_isProfileCompleted) // Conditional rendering
Column(

View File

@ -10,6 +10,7 @@ import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import '../../custom_drawer_routes.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class NotificationPage extends ConsumerStatefulWidget {
@override
@ -66,6 +67,7 @@ class _NotificationPageState extends ConsumerState<NotificationPage> {
setState(() {
notifications = List<Map<String, dynamic>>.from(
jsonResponse['data']); // Assign decoded data
print('notifications $notifications');
});
} else {
throw Exception('Failed to load data');
@ -100,13 +102,21 @@ class _NotificationPageState extends ConsumerState<NotificationPage> {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
fetchNotifications(localeCode);
});
final List<Map<String, dynamic>> tabs = [
{'title': AppLocalizations.of(context)!.all_updates},
{'title': AppLocalizations.of(context)!.app_updates},
{'title': AppLocalizations.of(context)!.notificationSocial},
{'title': AppLocalizations.of(context)!.notificationEconomy},
{'title': AppLocalizations.of(context)!.notificationEnvironment},
{'title': AppLocalizations.of(context)!.notificationFavourites},
];
// Filter notifications based on the selected tab
List<Map<String, dynamic>> filteredNotifications = selectedTabIndex == 0
? notifications
: notifications.where((notification) {
print(
"Comparing: '${notification["category"]}' with '${tabs[selectedTabIndex]}'");
return notification["category"] == tabs[selectedTabIndex];
// print("Comparing: '${notification["category"]}' with '${tabs[selectedTabIndex]}'");
return notification["category"] == tabs[selectedTabIndex]['title'];
}).toList();
return PopScope(
@ -125,7 +135,7 @@ class _NotificationPageState extends ConsumerState<NotificationPage> {
body: Column(
children: [
TabBarHeader(
tabs: tabs,
tabs: tabs.map((tab) => tab['title'] as String).toList(),
selectedIndex: selectedTabIndex,
onTabSelected: (index) {
setState(() {
@ -162,10 +172,12 @@ class _NotificationPageState extends ConsumerState<NotificationPage> {
),
),
child: NotificationTile(
title: notification['title'] ?? 'No Title',
date: formatDate(notification['created'] ?? ''),
category: notification['category'] ?? 'Unknown',
message: notification['message'] ?? ''),
title: notification['title'] ?? 'No Title',
date: formatDate(notification['created'] ?? ''),
category: notification['category'] ?? 'Unknown',
message: notification['message'] ?? '',
id: notification['id'],
),
);
},
),
@ -240,23 +252,28 @@ class NotificationTile extends StatelessWidget {
final String message;
final String date;
final String category;
final String id;
const NotificationTile({
required this.title,
required this.message,
required this.date,
required this.category,
required this.id,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
final encodedKey = Uri.encodeQueryComponent('notification');
context.go('/notification_details', extra: {
'title': title,
'message': message,
'date': date,
'category': category,
'id': id,
'backNavigation': encodedKey
});
},
child: ListTile(

View File

@ -1,14 +1,22 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:uae_stat/config/api_config.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import '../../custom_drawer_routes.dart';
import 'package:http/http.dart' as http;
class NotificationDetails extends ConsumerWidget {
class NotificationDetails extends ConsumerStatefulWidget {
final String title;
final String message;
final String date;
final String category;
final String id;
final String backNavigation;
const NotificationDetails({
super.key,
@ -16,10 +24,85 @@ class NotificationDetails extends ConsumerWidget {
required this.message,
required this.date,
required this.category,
required this.id,
required this.backNavigation,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
_NotificationDetailsState createState() => _NotificationDetailsState();
}
class _NotificationDetailsState extends ConsumerState<NotificationDetails> {
// Example notification data
final _pb = PocketBase(apiUrl);
Map<String, dynamic>? notification;
// Current selected tab index
int selectedTabIndex = 0;
late final Locale locale;
dynamic notificationID;
@override
void initState() {
super.initState();
print(widget.id);
locale = ref.read(localeProvider) ?? const Locale('en');
fetchNotifications(locale?.languageCode ?? 'en');
}
String formatDate(String dateString) {
try {
DateTime dateTime =
DateTime.parse(dateString); // Convert API date to DateTime
return DateFormat('dd MMM yyyy hh:mm a')
.format(dateTime); // Format DateTime
} catch (e) {
return 'Invalid Date'; // Handle parsing errors
}
}
Future<void> fetchNotifications(locale) async {
notificationID = widget.id;
final baseUrl = apiUrl + '/api/getNotification';
try {
final response = await http
.get(Uri.parse('$baseUrl?language=$locale&id=$notificationID'));
if (response.statusCode == 200) {
final Map<String, dynamic> jsonResponse =
jsonDecode(response.body); // Decode JSON
if (jsonResponse['message'] == 'Success') {
setState(() {
final data = jsonResponse['data'];
notification = data;
// if (data is Map<String, dynamic>) {
// notification = data;
// } else {
// notification = null; // Default to null if data is not valid
// }
print('notification $notification');
});
} else {
throw Exception('Failed to load data');
}
} else {
throw Exception(
'Failed to load data with status code ${response.statusCode}');
}
} catch (e) {
print('Error fetching data: $e');
}
}
@override
Widget build(BuildContext context) {
ref.listen<Locale?>(localeProvider, (previous, next) {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
fetchNotifications(localeCode);
});
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
@ -34,13 +117,14 @@ class NotificationDetails extends ConsumerWidget {
),
),
showBackButton: true,
navBackArrow: Text(widget.backNavigation ?? 'Default Value'),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
notification?['title'] ?? '',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
@ -52,7 +136,7 @@ class NotificationDetails extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
category == 'App updates'
notification?['category'] == 'App updates'
? 'assets/backgrounds/Notification/App-Update.png'
: 'assets/backgrounds/Notification/Update_notific.png',
height: 200,
@ -62,9 +146,8 @@ class NotificationDetails extends ConsumerWidget {
),
const SizedBox(height: 20),
Text(
message.isNotEmpty
? message
: "No additional details available.",
notification?['message'] ??
"No additional details available.",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
@ -72,11 +155,12 @@ class NotificationDetails extends ConsumerWidget {
),
const SizedBox(height: 10),
Text(
"Date: $date",
"Date: ${notification != null ? formatDate(notification!['created'] ?? '') : 'N/A'}",
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Color(0xFF8E8E8E)),
fontSize: 12,
fontWeight: FontWeight.w400,
color: Color(0xFF8E8E8E),
),
),
],
),

View File

@ -67,6 +67,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
String? userEmail;
String? userAvatar;
String? role;
String? preferredLanguage;
String? userNames;
String? userEmails;
String? userAvatars;
@ -654,17 +655,23 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
userEmail = userDetailsResponse.data['email'] ?? '';
userAvatar = userDetailsResponse.data['avatar'] ?? '';
role = userDetailsResponse.data['role'] ?? '';
preferredLanguage = userDetailsResponse.data['language'] ?? '';
String recordId = userId;
String collectionId =
userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_';
if (userAvatar!.isNotEmpty && recordId.isNotEmpty) {
_avatarUrl =
'$apiUrl/api/files/$collectionId/$recordId/$userAvatar';
_avatarUrl = '$apiUrl/api/files/$collectionId/$recordId/$userAvatar';
} else {
_avatarUrl = ''; // Reset to default or empty
}
});
// **Set Default Locale in Provider**
if (preferredLanguage == 'ar') {
ref.read(localeProvider.notifier).setLocale(const Locale('ar'));
} else {
ref.read(localeProvider.notifier).setLocale(const Locale('en'));
}
} catch (e) {
print('Error fetching user details: $e');
}
@ -706,7 +713,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
title: Padding(
padding: EdgeInsets.only(top: 10),
child: Align(
alignment: (locale?.languageCode == 'ar') ? Alignment.centerRight : Alignment.centerLeft,
alignment: (locale?.languageCode == 'ar')
? Alignment.centerRight
: Alignment.centerLeft,
child: DefaultTextStyle(
style: TextStyle(
color: widget.colorChange ? Colors.white : Color(0xFF414042),
@ -775,12 +784,12 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
color: widget.colorChange ? Colors.white : Colors.black,
icon: const Icon(Icons.arrow_back_ios_new, size: 24),
onPressed: () {
// if ((widget.navBackArrow as Text).data == 'home') {
// context.go('/myhomepage');
// } else {
// context.go('/uaenumbers');
// }
context.pop();
if ((widget.navBackArrow as Text).data ==
'notification') {
context.go('/notification');
} else {
context.pop();
}
},
),
),
@ -1195,7 +1204,7 @@ void _showLogoutConfirmationDialog(BuildContext context) {
),
actions: [
Row(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(