import SwiftUI struct HistoryRow: Identifiable { let entry: Entry let task: String let person: String let partner: String var id: String { entry.id } var date: String { entry.date } var note: String { entry.note } } struct HistoryView: View { @EnvironmentObject var store: Store @EnvironmentObject var ui: UIState @State private var query = "" @State private var taskFilter = "" @State private var selection = Set() @State private var sortOrder = [KeyPathComparator(\HistoryRow.date, order: .reverse)] private var rows: [HistoryRow] { let q = query.lowercased() return store.db.entries .filter { taskFilter.isEmpty || $0.task == taskFilter } .map { e in HistoryRow(entry: e, task: store.task(e.task)?.name ?? e.task, person: store.name(e.person), partner: e.partner.isEmpty ? "" : store.name(e.partner)) } .filter { q.isEmpty || "\($0.task) \($0.person) \($0.partner) \($0.note)".lowercased().contains(q) } .sorted(using: sortOrder) } var body: some View { let rows = rows VStack(spacing: 0) { HStack(spacing: 12) { TextField("Suchen (Name, Notiz …)", text: $query) .textFieldStyle(.roundedBorder) .frame(width: 260) Picker("Aufgabe", selection: $taskFilter) { Text("Alle Aufgaben").tag("") ForEach(store.db.tasks.filter { !$0.partnerColumn }) { Text($0.name).tag($0.id) } } .frame(width: 280) Text("\(rows.count) Einträge").foregroundStyle(Theme.muted) Spacer() Button("Bearbeiten") { edit(selection.first) }.disabled(selection.count != 1) Button("Löschen", role: .destructive) { delete(selection) }.disabled(selection.isEmpty) } .padding(16) Table(rows, selection: $selection, sortOrder: $sortOrder) { TableColumn("Datum", value: \.date) { Text(Day.display($0.date)).monospacedDigit() }.width(90) TableColumn("Aufgabe", value: \.task).width(min: 160, ideal: 220) TableColumn("Person", value: \.person).width(min: 140, ideal: 200) TableColumn("Partner", value: \.partner).width(min: 120, ideal: 180) TableColumn("Thema / Notiz", value: \.note) { Text($0.note).foregroundStyle(Theme.muted) } } .contextMenu(forSelectionType: String.self) { ids in if ids.count == 1 { Button("Bearbeiten") { edit(ids.first) } } Button("Löschen", role: .destructive) { delete(ids) } } primaryAction: { ids in edit(ids.first) } .onDeleteCommand { delete(selection) } .overlay { if store.db.entries.isEmpty { Text("Noch keine Einträge. Mit ⌘N oder einem Klick in die Übersicht geht's los.") .foregroundStyle(Theme.muted) } } } } private func edit(_ id: String?) { guard let id, let e = store.db.entries.first(where: { $0.id == id }) else { return } ui.draft = e } private func delete(_ ids: Set) { guard !ids.isEmpty else { return } let alert = NSAlert() alert.messageText = ids.count == 1 ? "Eintrag löschen?" : "\(ids.count) Einträge löschen?" alert.informativeText = "Das lässt sich nicht rückgängig machen." alert.addButton(withTitle: "Löschen").hasDestructiveAction = true alert.addButton(withTitle: "Abbrechen") guard alert.runModal() == .alertFirstButtonReturn else { return } ids.forEach(store.delete(entry:)) selection.subtract(ids) } }