diff --git a/LoopFollow/Alarm/AddAlarm/AddAlarmSheet.swift b/LoopFollow/Alarm/AddAlarm/AddAlarmSheet.swift index 17d5b73c1..b603f6152 100644 --- a/LoopFollow/Alarm/AddAlarm/AddAlarmSheet.swift +++ b/LoopFollow/Alarm/AddAlarm/AddAlarmSheet.swift @@ -7,22 +7,33 @@ struct AddAlarmSheet: View { let onSelect: (AlarmType) -> Void @Environment(\.dismiss) private var dismiss + @State private var searchText = "" + private let columns = [ GridItem(.adaptive(minimum: 110), spacing: 16), ] + private func matches(_ type: AlarmType) -> Bool { + let query = searchText.trimmingCharacters(in: .whitespacesAndNewlines) + guard !query.isEmpty else { return true } + return type.rawValue.localizedCaseInsensitiveContains(query) + || type.blurb.localizedCaseInsensitiveContains(query) + || type.group.rawValue.localizedCaseInsensitiveContains(query) + } + var body: some View { NavigationStack { ScrollView { LazyVGrid(columns: columns, spacing: 16) { ForEach(AlarmType.Group.allCases, id: \.self) { group in - if AlarmType.allCases.contains(where: { $0.group == group }) { + let types = AlarmType.allCases.filter { $0.group == group && matches($0) } + if !types.isEmpty { Section(header: Text(group.rawValue) .font(.headline) .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 4) ) { - ForEach(AlarmType.allCases.filter { $0.group == group }, id: \.self) { type in + ForEach(types, id: \.self) { type in AlarmTile(type: type) { onSelect(type) } @@ -32,8 +43,25 @@ struct AddAlarmSheet: View { } } .padding() + + if !AlarmType.allCases.contains(where: matches) { + VStack(spacing: 8) { + Image(systemName: "magnifyingglass") + .font(.largeTitle) + .foregroundColor(.secondary) + Text("No Results") + .font(.headline) + Text("No alarms match “\(searchText)”.") + .font(.subheadline) + .foregroundColor(.secondary) + .multilineTextAlignment(.center) + } + .padding(.top, 40) + .padding(.horizontal) + } } .navigationTitle("Add Alarm") + .searchable(text: $searchText, prompt: "Search alarms") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() }