import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:onufitness/constants/color_constant.dart'; import 'package:onufitness/constants/text_constant.dart'; import 'package:onufitness/controller/notification_controller.dart'; import 'package:onufitness/models/notification/get_all_notification_response_model.dart'; import 'package:onufitness/services/notification_services/navigation_controller.dart'; import 'package:onufitness/utils/helper_function.dart'; import 'package:onufitness/widgets/appbars/custom_appbar.dart'; import 'package:onufitness/widgets/Buttons/custom_submit_button.dart'; class NotificationScreen extends StatelessWidget { const NotificationScreen({super.key}); @override Widget build(BuildContext context) { final controller = Get.put(NotificationController()); return Scaffold( backgroundColor: Colors.white, appBar: CustomAppBar( title: "Notifications", titleFontSize: appBarHeardingText, textColor: appbarTextColor, backgroundColor: appBarBackgroundColor, leading: IconButton( onPressed: () { Get.back(); }, icon: Icon(Icons.arrow_back_ios), ), actions: [ Obx(() { if (controller.hasUnreadNotifications) { return Container( margin: EdgeInsets.only(right: 16.w), child: TextButton.icon( onPressed: controller.markAllAsRead, icon: Icon(Icons.done_all, size: 18.sp, color: Colors.black), label: Text( 'Mark all read', style: TextStyle( fontSize: smallSizeText, color: Colors.black, fontWeight: FontWeight.w500, ), ), style: TextButton.styleFrom( backgroundColor: Colors.grey.withValues(alpha: 0.2), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.r), ), ), ), ); } return const SizedBox.shrink(); }), ], ), body: RefreshIndicator( onRefresh: controller.refreshNotifications, backgroundColor: Colors.white, color: Colors.black, child: Obx(() { if (controller.isLoading.value) { return Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.black), ), ); } if (controller.errorMessage.value != null) { return _buildErrorState(controller); } if (controller.notifications.isEmpty) { return _buildEmptyState(); } return _buildNotificationList(controller); }), ), ); } Widget _buildErrorState(NotificationController controller) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.error_outline, size: 60.sp, color: Colors.red[300]), SizedBox(height: 16.h), Text( "Server error!", style: TextStyle(fontSize: regularSizeText, color: Colors.red[600]), ), SizedBox(height: 16.h), CustomSubmitButton( width: 100.w, height: 40.h, text: "Retry", onPressed: () => controller.fetchNotifications(isRefresh: true), ), ], ), ); } Widget _buildEmptyState() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.notifications_none, size: 80.sp, color: Colors.grey[400]), SizedBox(height: 16.h), Text( 'No notifications yet', style: TextStyle( fontSize: largeSizeText, color: Colors.grey[600], fontWeight: FontWeight.w500, ), ), SizedBox(height: 8.h), Text( 'You\'ll see notifications here when you have them', style: TextStyle(fontSize: smallSizeText, color: Colors.grey[500]), textAlign: TextAlign.center, ), ], ), ); } Widget _buildNotificationList(NotificationController controller) { return Column( children: [ Obx(() { if (controller.hasUnreadNotifications) { return _buildUnreadCountHeader(controller); } return const SizedBox.shrink(); }), Expanded( child: Obx( () => ListView.builder( controller: controller.scrollController, padding: EdgeInsets.symmetric(horizontal: 15.w), itemCount: controller.notifications.length + (controller.isLoadingMore.value ? 1 : 0), itemBuilder: (context, index) { // Show loading indicator at the end when loading more if (index == controller.notifications.length) { return _buildLoadingMoreIndicator(); } final notification = controller.notifications[index]; return _buildNotificationCard(notification, controller); }, ), ), ), ], ); } Widget _buildLoadingMoreIndicator() { return Container( padding: EdgeInsets.all(16.w), child: Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.black), strokeWidth: 2, ), ), ); } Widget _buildUnreadCountHeader(NotificationController controller) { return Container( width: double.infinity, padding: EdgeInsets.all(16.w), margin: EdgeInsets.all(16.w), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Color(primaryColor), Color(primaryColor).withValues(alpha: 0.2), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12.r), ), child: Row( children: [ Container( padding: EdgeInsets.all(7.w), decoration: BoxDecoration( color: Colors.black, shape: BoxShape.circle, ), child: Icon( Icons.notifications, color: Colors.white, size: isTablet ? 25.sp : 20.sp, ), ), SizedBox(width: 12.w), Expanded( child: Text( '${controller.totalUnseenCount} unread notifications', style: TextStyle( fontSize: regularSizeText, fontWeight: FontWeight.w500, color: Colors.black, ), ), ), ], ), ); } Widget _buildNotificationCard( NotificationItem notification, NotificationController controller, ) { return Container( margin: EdgeInsets.only(bottom: 12.h), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.r), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], border: notification.isSeen != true ? Border.all(color: Color(primaryColor), width: 2) : null, ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(16.r), onTap: () async { if (notification.isSeen != true) { controller.markNotificationAsRead(notification.notificationId!); } await Future.delayed(const Duration(milliseconds: 500)); // if (!Get.isRegistered()) { // Get.put(NotificationNavigationController()); // } final navigationController = Get.find(); await navigationController.navigateBasedOnNotification({ "notificationType": notification.notificationType, "dataId": notification.dataField, }); }, child: Padding( padding: EdgeInsets.all(16.w), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 50.w, height: 50.w, decoration: BoxDecoration( color: controller .getNotificationColor(notification.notificationType) .withValues(alpha: 0.1), shape: BoxShape.circle, ), child: Icon( controller.getNotificationIcon( notification.notificationType, ), color: controller.getNotificationColor( notification.notificationType, ), size: 24.sp, ), ), SizedBox(width: 16.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( notification.notificationTitle ?? 'No Title', style: TextStyle( fontSize: regularSizeText, fontWeight: notification.isSeen == true ? FontWeight.w500 : FontWeight.w600, color: notification.isSeen == true ? Colors.grey[700] : Colors.black, ), maxLines: 2, ), ), if (notification.isSeen != true) Container( width: 8.w, height: 8.w, decoration: BoxDecoration( color: Colors.blue[600], shape: BoxShape.circle, ), ), ], ), SizedBox(height: 4.h), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( _formatTimeAgo(notification.createdAt), style: TextStyle( fontSize: smallSizeText, color: Colors.grey[500], ), ), ], ), ], ), ), ], ), ), ), ), ); } String _formatTimeAgo(dynamic createdAt) { if (createdAt == null) return 'Unknown time'; DateTime? dateTime; // Handle different date formats if (createdAt is String) { try { dateTime = DateTime.parse(createdAt); } catch (e) { return 'Unknown time'; } } else if (createdAt is DateTime) { dateTime = createdAt; } else { return 'Unknown time'; } final now = DateTime.now(); final difference = now.difference(dateTime); if (difference.inDays > 7) { return '${(difference.inDays / 7).floor()}w ago'; } else if (difference.inDays > 0) { return '${difference.inDays}d ago'; } else if (difference.inHours > 0) { return '${difference.inHours}h ago'; } else if (difference.inMinutes > 0) { return '${difference.inMinutes}m ago'; } else { return 'Just now'; } } }