You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.8 KiB

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<String>()
@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<String>) {
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)
}
}

Powered by TurnKey Linux.