// Views/Dashboard/NotificationsView.swift import SwiftUI import SwiftData import MessageUI // MARK: - Notifications Inbox // Shows the most recent notifications fetched during polling. // Notifications are already marked read on the server by pollNotifications(). struct NotificationsView: View { @EnvironmentObject private var sync: SyncManager var body: some View { Group { if sync.recentNotifications.isEmpty { if !sync.isOnline { ContentUnavailableView( "Offline", systemImage: "wifi.slash", description: Text("Notifications are delivered when you go online.") ) } else { ContentUnavailableView( "No Notifications", systemImage: "bell.slash", description: Text("You\'re all caught up.") ) } } else { List(sync.recentNotifications) { notif in VStack(alignment: .leading, spacing: 6) { HStack(alignment: .top) { Image(systemName: iconName(for: notif.eventType)) .foregroundStyle(iconColor(for: notif.eventType)) .frame(width: 24) VStack(alignment: .leading, spacing: 2) { Text(notif.title) .font(.callout.bold()) .lineLimit(2) Text(notif.body) .font(.caption) .foregroundStyle(.secondary) .lineLimit(3) } } if let date = SyncManager.isoFormatter.date(from: notif.createdAt) { Text(date.formatted(.relative(presentation: .named))) .font(.caption2) .foregroundStyle(.tertiary) } } .padding(.vertical, 4) } } } .navigationTitle("Notifications") .navigationBarTitleDisplayMode(.large) .onAppear { sync.markNotificationsViewed() } .refreshable { await sync.pollNotifications() sync.markNotificationsViewed() } } private func iconName(for eventType: String?) -> String { switch eventType { case "inspection_completed": return "checkmark.circle.fill" case "issue_flagged": return "exclamationmark.triangle.fill" case "issue_resolved": return "checkmark.seal.fill" case "sla_alert": return "clock.badge.exclamationmark" case "follow_up_required": return "exclamationmark.arrow.circlepath" default: return "bell.fill" } } private func iconColor(for eventType: String?) -> Color { switch eventType { case "inspection_completed": return .green case "issue_flagged": return .orange case "issue_resolved": return .green case "sla_alert": return .red case "follow_up_required": return .orange default: return .blue } } }