add ExerciseEditor, Picker skeletons, AutocompleteTextfield
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// AutocompleteTextField.swift
|
||||
// WorkoutsPlus
|
||||
//
|
||||
// Created by Felix Förtsch on 19.09.24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AutocompleteTextField<Item: Nameable>: View {
|
||||
var placeholder: String
|
||||
|
||||
@Binding var item: Item?
|
||||
var items: [Item]
|
||||
|
||||
@State private var searchText = ""
|
||||
var filteredItems: [Item] {
|
||||
if searchText.isEmpty {
|
||||
return []
|
||||
} else {
|
||||
return items.filter { $0.name.localizedCaseInsensitiveContains(searchText) }
|
||||
}
|
||||
}
|
||||
|
||||
@State private var isAutoCompleteShown: Bool = true
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
HStack {
|
||||
TextField(placeholder, text: $searchText)
|
||||
// TODO: Fix "List line" not extending to the full width
|
||||
if item == nil && !searchText.isEmpty {
|
||||
Text("NEW")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.green)
|
||||
}
|
||||
if item != nil {
|
||||
Text("EDIT")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
}
|
||||
.onAppear() {
|
||||
if item != nil {
|
||||
self.searchText = item!.name
|
||||
}
|
||||
}
|
||||
.onChange(of: searchText) {
|
||||
if filteredItems.count == 1 && filteredItems.first?.name == searchText {
|
||||
self.item = filteredItems.first
|
||||
isAutoCompleteShown = false
|
||||
} else {
|
||||
self.item = nil
|
||||
isAutoCompleteShown = true
|
||||
}
|
||||
}
|
||||
if isAutoCompleteShown {
|
||||
ForEach(filteredItems, id: \.self) { item in
|
||||
HStack {
|
||||
Text(item.name)
|
||||
.foregroundStyle(.gray)
|
||||
Spacer()
|
||||
Image(systemName: "arrow.up.left")
|
||||
.foregroundStyle(.blue)
|
||||
}
|
||||
// This .contentShape makes the whole row tappable
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
self.item = item
|
||||
searchText = item.name
|
||||
isAutoCompleteShown = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct Item: Nameable {
|
||||
var id = UUID()
|
||||
var name: String
|
||||
}
|
||||
|
||||
#Preview {
|
||||
@Previewable @State var item: Item? = nil
|
||||
VStack {
|
||||
Text("Preview only: ")
|
||||
Text(item?.name ?? "No item selected")
|
||||
}
|
||||
.background(.red)
|
||||
List {
|
||||
AutocompleteTextField<Item>(placeholder: "New Item", item: $item, items: [
|
||||
Item(name: "Item 1"),
|
||||
Item(name: "Item 2"),
|
||||
Item(name: "Item 3")
|
||||
])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user