Initial commit
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../providers/notifications_provider.dart';
|
||||
import '../../providers/profile_provider.dart';
|
||||
import '../../providers/tasks_provider.dart';
|
||||
import '../../providers/tickets_provider.dart';
|
||||
import '../../widgets/responsive_body.dart';
|
||||
|
||||
class NotificationsScreen extends ConsumerWidget {
|
||||
const NotificationsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final notificationsAsync = ref.watch(notificationsProvider);
|
||||
final profilesAsync = ref.watch(profilesProvider);
|
||||
final ticketsAsync = ref.watch(ticketsProvider);
|
||||
final tasksAsync = ref.watch(tasksProvider);
|
||||
|
||||
final profileById = {
|
||||
for (final profile in profilesAsync.valueOrNull ?? [])
|
||||
profile.id: profile,
|
||||
};
|
||||
final ticketById = {
|
||||
for (final ticket in ticketsAsync.valueOrNull ?? []) ticket.id: ticket,
|
||||
};
|
||||
final taskById = {
|
||||
for (final task in tasksAsync.valueOrNull ?? []) task.id: task,
|
||||
};
|
||||
|
||||
return ResponsiveBody(
|
||||
child: notificationsAsync.when(
|
||||
data: (items) {
|
||||
if (items.isEmpty) {
|
||||
return const Center(child: Text('No notifications yet.'));
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16, bottom: 8),
|
||||
child: Text(
|
||||
'Notifications',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
itemCount: items.length,
|
||||
separatorBuilder: (context, index) =>
|
||||
const SizedBox(height: 12),
|
||||
itemBuilder: (context, index) {
|
||||
final item = items[index];
|
||||
final actorName = item.actorId == null
|
||||
? 'System'
|
||||
: (profileById[item.actorId]?.fullName ??
|
||||
item.actorId!);
|
||||
final ticketSubject = item.ticketId == null
|
||||
? 'Ticket'
|
||||
: (ticketById[item.ticketId]?.subject ??
|
||||
item.ticketId!);
|
||||
final taskTitle = item.taskId == null
|
||||
? 'Task'
|
||||
: (taskById[item.taskId]?.title ?? item.taskId!);
|
||||
final subtitle = item.taskId != null
|
||||
? taskTitle
|
||||
: ticketSubject;
|
||||
|
||||
final title = _notificationTitle(item.type, actorName);
|
||||
final icon = _notificationIcon(item.type);
|
||||
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(title),
|
||||
subtitle: Text(subtitle),
|
||||
trailing: item.isUnread
|
||||
? const Icon(
|
||||
Icons.circle,
|
||||
size: 10,
|
||||
color: Colors.red,
|
||||
)
|
||||
: null,
|
||||
onTap: () async {
|
||||
final ticketId = item.ticketId;
|
||||
final taskId = item.taskId;
|
||||
if (ticketId != null) {
|
||||
await ref
|
||||
.read(notificationsControllerProvider)
|
||||
.markReadForTicket(ticketId);
|
||||
} else if (taskId != null) {
|
||||
await ref
|
||||
.read(notificationsControllerProvider)
|
||||
.markReadForTask(taskId);
|
||||
} else if (item.isUnread) {
|
||||
await ref
|
||||
.read(notificationsControllerProvider)
|
||||
.markRead(item.id);
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
if (taskId != null) {
|
||||
context.go('/tasks/$taskId');
|
||||
} else if (ticketId != null) {
|
||||
context.go('/tickets/$ticketId');
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) =>
|
||||
Center(child: Text('Failed to load notifications: $error')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _notificationTitle(String type, String actorName) {
|
||||
switch (type) {
|
||||
case 'assignment':
|
||||
return '$actorName assigned you';
|
||||
case 'created':
|
||||
return '$actorName created a new item';
|
||||
case 'mention':
|
||||
default:
|
||||
return '$actorName mentioned you';
|
||||
}
|
||||
}
|
||||
|
||||
IconData _notificationIcon(String type) {
|
||||
switch (type) {
|
||||
case 'assignment':
|
||||
return Icons.assignment_ind_outlined;
|
||||
case 'created':
|
||||
return Icons.campaign_outlined;
|
||||
case 'mention':
|
||||
default:
|
||||
return Icons.alternate_email;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user