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 '../../core/theme/app_theme.dart'; import '../../core/api/api_client.dart'; import '../../shared/models/notification.dart'; import '../../shared/providers/lookup_providers.dart'; final notificationsProvider = FutureProvider.autoDispose>((ref) async { final resp = await apiDio.get('/notifications'); return (resp.data as List).map((e) => AppNotification.fromJson(e)).toList(); }); class NotificationScreen extends ConsumerWidget { const NotificationScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(notificationsProvider); return Scaffold( appBar: AppBar( title: const Text('Notifications'), actions: [ TextButton( onPressed: () async { await apiDio.post('/notifications/read-all'); ref.invalidate(notificationsProvider); ref.invalidate(notifUnreadCountProvider); }, child: const Text('Mark all as read'), ), ], ), body: async.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text(e.toString())), data: (notifs) { if (notifs.isEmpty) return const Center( child: Column(mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.notifications_none, size: 56, color: AppColors.textSub), SizedBox(height: 12), Text('No notifications', style: TextStyle(color: AppColors.textSub)), ]), ); return RefreshIndicator( color: AppColors.primary, onRefresh: () async { ref.invalidate(notificationsProvider); ref.invalidate(notifUnreadCountProvider); }, child: ListView.separated( itemCount: notifs.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (_, i) { final n = notifs[i]; return ListTile( tileColor: n.isRead ? null : AppColors.blueLight, leading: CircleAvatar( radius: 20, backgroundColor: n.isRead ? AppColors.bg : AppColors.primaryLight, child: Icon(Icons.notifications_outlined, size: 18, color: n.isRead ? AppColors.textSub : AppColors.primary), ), title: Text(n.title, style: TextStyle( fontSize: 13, fontWeight: n.isRead ? FontWeight.w400 : FontWeight.w600)), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (n.body != null) Text(n.body!, style: const TextStyle(fontSize: 12, color: AppColors.textSub)), Text(DateFormat('d MMM yyyy HH:mm').format(n.createdAt), style: const TextStyle(fontSize: 11, color: AppColors.textSub)), ], ), trailing: !n.isRead ? Container( width: 8, height: 8, decoration: const BoxDecoration(color: AppColors.blue, shape: BoxShape.circle), ) : null, onTap: () async { if (!n.isRead) { await apiDio.post('/notifications/${n.id}/read'); ref.invalidate(notificationsProvider); ref.invalidate(notifUnreadCountProvider); } if (n.link != null && context.mounted) context.push(n.link!); }, ); }, ), ); }, ), ); } }