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:shared_preferences/shared_preferences.dart'; import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/connectivity_provider.dart'; import 'package:uae_stat/config/theme/service.dart'; import 'package:uae_stat/config/theme/theme_provider.dart'; import 'package:uae_stat/config/toggle_lang_service.dart'; 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:uae_stat/l10n/app_localizations.dart'; class NotificationPage extends ConsumerStatefulWidget { @override _NotificationPageState createState() => _NotificationPageState(); } class _NotificationPageState extends ConsumerState { // Example notification data final _pb = PocketBase(apiUrl); bool isLoading = true; List> notifications = []; List userReadedNotiOrNot = []; String notificationCount = ''; List homePageData = []; List filteredData = []; // Current selected tab index int selectedTabIndex = 0; late final Locale locale; dynamic userID; late UserService _userService; late ThemeMode currentTheme; // Tab categories // final List tabs = [ // "All updates", // "App updates", // "Social", // "Economy", // "Environment", // "Favourites" // ]; @override void initState() { super.initState(); locale = ref.read(localeProvider) ?? const Locale('en'); _userService = UserService(); _initializePage(); currentTheme = ref.read(themeProvider); WidgetsBinding.instance.addPostFrameCallback((_) { final isDark = currentTheme == ThemeMode.dark || (currentTheme == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.dark); final themeMode = (isDark ? 'dark' : 'light'); fetchData(locale?.languageCode ?? 'en', themeMode); }); } Future fetchData(locale, themeMode) async { const baseUrl = '${apiUrl}api/getUAENumbersData'; try { final response = await http.get( Uri.parse(baseUrl + '?language=$locale&color_mode=$themeMode'), headers: {'APP_SIGNATURE': 'fcsc.gov.ae.X7pL9qZm2A'}); if (response.statusCode == 200) { setState(() { homePageData = (json.decode(response.body) as List) .map((e) => Map.from(e)) .toList(); filteredData = List.from(homePageData); isLoading = false; }); } else { throw Exception('Failed to load data'); } } catch (e) { setState(() { isLoading = false; }); } } Future _initializePage() async { final prefs = await SharedPreferences.getInstance(); userReadedNotiOrNot = prefs.getStringList('read_notification_ids') ?? []; await fetchNotifications(locale.languageCode); _processNotifications(notifications, userReadedNotiOrNot); } void _processNotifications( List> notification, List push) { int count = 0; for (var product in notification) { if (push.contains(product['id'])) { count++; } } if (count > 0) { notificationCount = '($count)'; } else { notificationCount = ''; } } 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 fetchNotifications(locale) async { final baseUrl = apiUrl + 'api/getNotification'; try { final response = await http.get(Uri.parse('$baseUrl?language=$locale'), headers: {'APP_SIGNATURE': 'fcsc.gov.ae.X7pL9qZm2A'}); if (response.statusCode == 200) { final Map jsonResponse = jsonDecode(response.body); // Decode JSON if (jsonResponse['message'] == 'Success') { setState(() { notifications = List>.from( jsonResponse['data']); isLoading = false; }); } else { setState(() { isLoading = false; }); throw Exception('Failed to load data'); } } else { setState(() { isLoading = false; }); throw Exception( 'Failed to load data with status code ${response.statusCode}'); } } catch (e) { setState(() { isLoading = false; }); } } @override Widget build(BuildContext context) { ref.listen>(connectivityProvider, (previous, hasInternet) { if (hasInternet.value == false) { context.push('/internetcheck'); } }); // ref.listen(localeProvider, (previous, next) async { // final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null // setState(() { // isLoading = true; // }); // await _userService.updateLanguage(localeCode); // fetchNotifications(localeCode); // }); ref.listen(localeProvider, (previous, next) async { final localeCode = next?.languageCode ?? 'en'; setState(() { isLoading = true; }); await _userService.updateLanguage(localeCode, ref); final currentTheme = ref.read(themeProvider); final isDark = currentTheme == ThemeMode.dark || (currentTheme == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.dark); final themeString = isDark ? 'dark' : 'light'; fetchData(localeCode, themeString); await fetchNotifications(localeCode); _processNotifications(notifications, userReadedNotiOrNot); }); ref.listen(themeProvider, (previous, next) async { final localeCode = ref.watch(localeProvider)?.languageCode ?? 'en'; // Default to 'en' if null setState(() { isLoading = true; }); final currentTheme = ref.read(themeProvider); final isDark = currentTheme == ThemeMode.dark || (currentTheme == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.dark); final themeString = isDark ? 'dark' : 'light'; fetchData(localeCode, themeString); await fetchNotifications(localeCode); _processNotifications(notifications, userReadedNotiOrNot); }); final themeMode = ref.read(themeProvider); final isDarkTheme = themeMode == ThemeMode.dark || (themeMode == ThemeMode.system && MediaQuery.of(context).platformBrightness == Brightness.dark); final List> 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}, ]; // final List> tabs = [ // { // 'title': AppLocalizations.of(context)!.all_updates, // 'color': Colors.blue, // }, // { // 'title': AppLocalizations.of(context)!.app_updates, // 'color': Colors.green, // }, // { // 'title': AppLocalizations.of(context)!.notificationSocial, // 'color': Color(0xFF675863), // }, // { // 'title': AppLocalizations.of(context)!.notificationEconomy, // 'color': Color(0xFF89AFD8), // }, // { // 'title': AppLocalizations.of(context)!.notificationEnvironment, // 'color': Color(0xFFB3CF99), // }, // { // 'title': AppLocalizations.of(context)!.notificationFavourites, // 'color': Colors.red, // }, // ]; // Filter notifications based on the selected tab List> filteredNotifications = selectedTabIndex == 0 ? notifications : notifications.where((notification) { // print("Comparing: '${notification["category"]}' with '${tabs[selectedTabIndex]}'"); return notification["category"] == tabs[selectedTabIndex]['title']; }).toList(); return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) { if (didPop) return; context.go('/myhomepage'); }, child: BaseScaffold( backgroundColor: isDarkTheme ? Colors.black : Colors.white, appbarColor: isDarkTheme ? Colors.black : Colors.white, title: Text( context.translate( 'Notification $notificationCount', '$notificationCount إشعار ', ), style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', )), ), body: isLoading ? Container( // color: Color(0x98FFFCE5), // Semi-transparent background color: isDarkTheme ? Colors.black : Color(0x98FFFCE5), // Semi-transparent background child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( margin: EdgeInsets.symmetric( horizontal: 40), // Left & Right space child: LinearProgressIndicator( minHeight: 5, // Adjust thickness backgroundColor: Colors.grey[100], // Optional: Background color valueColor: AlwaysStoppedAnimation( Color(0xFFAA8E83)), // Loader color ), ), ], ), ) : Column( children: [ TabBarHeader( tabs: tabs.map((tab) => tab['title'] as String).toList(), selectedIndex: selectedTabIndex, isDarkTheme: isDarkTheme, onTabSelected: (index) { setState(() { selectedTabIndex = index; }); }, ), Expanded( child: filteredNotifications.isEmpty ? Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.info_outline, size: 100, color: Colors.grey[400]), SizedBox(height: 16), Text( 'No notifications available.', style: TextStyle( fontSize: 16, color: Colors.grey, fontFamily: context.translate( 'Roboto', 'NotoKufi', ), ), ), ], ), ) : ListView.builder( itemCount: filteredNotifications.length, itemBuilder: (context, index) { final notification = filteredNotifications[index]; return Container( decoration: BoxDecoration( border: Border( bottom: BorderSide( color: Color(0xFFDEDEDE), width: 1), // Bottom border only ), ), child: NotificationTile( title: notification['title'] ?? 'No Title', date: formatDate(notification['created'] ?? ''), category: notification['category'] ?? 'Unknown', message: notification['message'] ?? '', id: notification['id'], userReadedNotiOrNot: userReadedNotiOrNot, userID: userID, isDarkTheme: isDarkTheme, ), ); }, ), ), ], ), ), ); } } class TabBarHeader extends StatelessWidget { final List tabs; final int selectedIndex; final ValueChanged onTabSelected; bool isDarkTheme; TabBarHeader({ required this.tabs, required this.selectedIndex, required this.onTabSelected, required this.isDarkTheme, }); @override Widget build(BuildContext context) { return Container( color: isDarkTheme ? Colors.black : Colors.white, padding: const EdgeInsets.symmetric(vertical: 8), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: tabs.asMap().entries.map((entry) { int index = entry.key; String text = entry.value; return Row( children: [ TextButton( onPressed: () => onTabSelected(index), style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith((states) { return selectedIndex == index ? isDarkTheme ? Color(0xFFFFFFFF) : Color(0xFFB68A34) : isDarkTheme ? Color(0xFFBBBBBB) : Color(0xFF898C81); }), ), child: Text( text, style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), ), ), ), if (index < tabs.length - 1) buildDivider(), ], ); }).toList(), ), ), ); } Widget buildDivider() { return Container( height: 20, child: const VerticalDivider( color: Colors.grey, thickness: 1, width: 16, ), ); } } class NotificationTile extends ConsumerWidget { final String title; final String message; final String date; final String category; final String id; final String userID; final List userReadedNotiOrNot; bool isDarkTheme; NotificationTile({ required this.title, required this.message, required this.date, required this.category, required this.id, required this.userID, required this.userReadedNotiOrNot, required this.isDarkTheme, }); @override Widget build(BuildContext context, WidgetRef ref) { bool isPushed = userReadedNotiOrNot.contains(id); return GestureDetector( onTap: () { readedNotification(userID, id, ref); final encodedKey = Uri.encodeQueryComponent('notification'); context.go('/notification_details', extra: { 'title': title, 'message': message, 'date': date, 'category': category, 'id': id, 'backNavigation': encodedKey }); }, child: ListTile( // leading: isPushed // ? const Icon(Icons.circle, size: 12, color: Color(0xFFFF274E)) // : Icon(Icons.circle, // size: 12, // color: isDarkTheme ? Colors.white : const Color(0x99414042)), // leading: isPushed // ? const Icon(Icons.circle, size: 12, color: Color(0xFFFF274E)) // : const Icon(Icons.circle, size: 12, color: Colors.transparent), title: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(top: 4.0, right: 6), child: isPushed ? const Icon(Icons.circle, size: 8, color: Color(0xFFFF274E)) : const Icon(Icons.circle, size: 8, color: Colors.transparent), ), Expanded( child: Text( title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, fontFamily: context.translate('Roboto', 'NotoKufi'), color: isPushed ? (isDarkTheme ? Colors.white : Color(0xFF414042)) // dark title : (isDarkTheme ? Color(0xFF999999) : Color(0x99414042)), // light grey title ), ), ), ], ), // Text( // title, // style: TextStyle( // color: isPushed // ? isDarkTheme // ? Colors.white // : Color(0xFF414042) // : isDarkTheme ? Color(0xFF999999) : Color(0xFF999999), // fontWeight: FontWeight.bold, // fontFamily: context.translate( // 'Roboto', // 'NotoKufi', // ), // ), // ), subtitle: Padding( padding: const EdgeInsets.only( left: 15), // 👈 set your desired left padding here child: Text( date, style: TextStyle( color: isDarkTheme ? Color(0xFF565656) : Color(0xFF8E8E8E), fontSize: 12, fontWeight: FontWeight.w400, fontFamily: context.translate( 'Roboto', 'NotoKufi', ), ), ), ), trailing: const Icon(Icons.arrow_forward_ios, size: 16, color: Color(0xFF898C81)), ), ); } } Future readedNotification( String userId, String notificationId, WidgetRef ref) async { final prefs = await SharedPreferences.getInstance(); final read = prefs.getStringList('read_notification_ids') ?? []; if (!read.contains(notificationId)) { read.add(notificationId); await prefs.setStringList('read_notification_ids', read); } }