06/22 Fix Low impact items
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user