Inventory screen selection mode update
This commit is contained in:
@@ -28,13 +28,25 @@ final class InventoryViewModel {
|
||||
errorMessage = "Failed to delete"
|
||||
}
|
||||
}
|
||||
|
||||
func deleteSelected(ids: Set<String>) async {
|
||||
for id in ids {
|
||||
guard let chemical = chemicals.first(where: { $0.id == id }) else { continue }
|
||||
do {
|
||||
try await client.delete(id: chemical.id)
|
||||
chemicals.removeAll { $0.id == id }
|
||||
} catch {
|
||||
errorMessage = "Failed to delete some items"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InventoryView: View {
|
||||
@State private var viewModel = InventoryViewModel()
|
||||
@State private var showAddSheet = false
|
||||
@State private var showScanSheet = false
|
||||
@State private var addMode: AddMode?
|
||||
@State private var isSelectMode = false
|
||||
@State private var selectedIDs: Set<String> = []
|
||||
|
||||
enum AddMode: String, Identifiable {
|
||||
case manual, scan
|
||||
@@ -56,24 +68,79 @@ struct InventoryView: View {
|
||||
} else {
|
||||
List {
|
||||
ForEach(viewModel.chemicals) { chemical in
|
||||
NavigationLink(destination: ChemicalDetailView(chemical: chemical)) {
|
||||
if isSelectMode {
|
||||
Button {
|
||||
if selectedIDs.contains(chemical.id) {
|
||||
selectedIDs.remove(chemical.id)
|
||||
} else {
|
||||
selectedIDs.insert(chemical.id)
|
||||
}
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: selectedIDs.contains(chemical.id) ? "checkmark.circle.fill" : "circle")
|
||||
.foregroundStyle(selectedIDs.contains(chemical.id) ? .blue : .secondary)
|
||||
.font(.title3)
|
||||
.animation(.easeInOut(duration: 0.15), value: selectedIDs.contains(chemical.id))
|
||||
ChemicalRowView(chemical: chemical)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.onDelete { indexSet in
|
||||
.buttonStyle(.plain)
|
||||
} else {
|
||||
NavigationLink(destination: ChemicalDetailView(chemical: chemical)) {
|
||||
ChemicalRowView(chemical: chemical)
|
||||
.frame(maxWidth: .infinity, alignment: .leading) // 📍 Force it to fill the row
|
||||
.contentShape(Rectangle()) // 📍 Make the transparent space tappable
|
||||
}
|
||||
.simultaneousGesture(
|
||||
LongPressGesture(minimumDuration: 0.5).onEnded { _ in
|
||||
withAnimation {
|
||||
isSelectMode = true
|
||||
selectedIDs = [chemical.id]
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
.onDelete(perform: isSelectMode ? nil : { indexSet in
|
||||
for index in indexSet {
|
||||
let chemical = viewModel.chemicals[index]
|
||||
Task { await viewModel.delete(chemical: chemical) }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
.refreshable {
|
||||
await viewModel.loadChemicals()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Inventory")
|
||||
.navigationTitle(isSelectMode ? "\(selectedIDs.count) Selected" : "Inventory")
|
||||
.toolbar {
|
||||
if isSelectMode {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button("Cancel") {
|
||||
withAnimation {
|
||||
isSelectMode = false
|
||||
selectedIDs = []
|
||||
}
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button(role: .destructive) {
|
||||
Task {
|
||||
await viewModel.deleteSelected(ids: selectedIDs)
|
||||
withAnimation {
|
||||
isSelectMode = false
|
||||
selectedIDs = []
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Text("Delete (\(selectedIDs.count))")
|
||||
}
|
||||
.disabled(selectedIDs.isEmpty)
|
||||
}
|
||||
} else {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Menu {
|
||||
Button {
|
||||
@@ -91,6 +158,7 @@ struct InventoryView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.alert("Error", isPresented: .constant(viewModel.errorMessage != nil)) {
|
||||
Button("OK") { viewModel.errorMessage = nil }
|
||||
} message: {
|
||||
|
||||
Reference in New Issue
Block a user