Creating and updating recipes works in the new edit view
This commit is contained in:
@@ -267,17 +267,7 @@ fileprivate struct DurationPicker: View {
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text(title)
|
||||
Spacer()
|
||||
TextField("00", text: $duration.hourComponent)
|
||||
.keyboardType(.decimalPad)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.multilineTextAlignment(.trailing)
|
||||
.frame(maxWidth: 40)
|
||||
Text(":")
|
||||
TextField("00", text: $duration.minuteComponent)
|
||||
.keyboardType(.decimalPad)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(maxWidth: 40)
|
||||
|
||||
}
|
||||
.frame(maxHeight: 40)
|
||||
.clipped()
|
||||
|
||||
@@ -102,19 +102,33 @@ struct RecipeView: View {
|
||||
.navigationTitle(viewModel.showTitle ? viewModel.recipe.name : "")
|
||||
.toolbar {
|
||||
if viewModel.editMode {
|
||||
// Cancel Button
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button("Cancel") {
|
||||
viewModel.editMode = false
|
||||
}
|
||||
}
|
||||
|
||||
// Upload Button
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button {
|
||||
// TODO: POST edited recipe
|
||||
if viewModel.newRecipe {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
} else {
|
||||
viewModel.editMode = false
|
||||
Task {
|
||||
if viewModel.newRecipe {
|
||||
if let res = await uploadNewRecipe() {
|
||||
viewModel.alertType = res
|
||||
viewModel.presentAlert = true
|
||||
} else {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
} else {
|
||||
if let res = await uploadEditedRecipe() {
|
||||
viewModel.alertType = res
|
||||
viewModel.presentAlert = true
|
||||
} else {
|
||||
viewModel.editMode = false
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
if viewModel.newRecipe {
|
||||
@@ -124,6 +138,8 @@ struct RecipeView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Button
|
||||
if !viewModel.newRecipe {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Menu {
|
||||
|
||||
@@ -12,21 +12,43 @@ import SwiftUI
|
||||
|
||||
struct RecipeDurationSection: View {
|
||||
@ObservedObject var viewModel: RecipeView.ViewModel
|
||||
@State var presentPopover: Bool = false
|
||||
|
||||
var body: some View {
|
||||
if viewModel.editMode {
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 200, maximum: .infinity), alignment: .leading)]) {
|
||||
EditableDurationView(time: viewModel.observableRecipeDetail.prepTime, title: LocalizedStringKey("Preparation"))
|
||||
EditableDurationView(time: viewModel.observableRecipeDetail.cookTime, title: LocalizedStringKey("Cooking"))
|
||||
EditableDurationView(time: viewModel.observableRecipeDetail.totalTime, title: LocalizedStringKey("Total time"))
|
||||
}
|
||||
} else {
|
||||
if !viewModel.editMode {
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 200, maximum: .infinity), alignment: .leading)]) {
|
||||
DurationView(time: viewModel.observableRecipeDetail.prepTime, title: LocalizedStringKey("Preparation"))
|
||||
DurationView(time: viewModel.observableRecipeDetail.cookTime, title: LocalizedStringKey("Cooking"))
|
||||
DurationView(time: viewModel.observableRecipeDetail.totalTime, title: LocalizedStringKey("Total time"))
|
||||
}
|
||||
} else {
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: 200, maximum: .infinity), alignment: .leading)]) {
|
||||
Button {
|
||||
presentPopover.toggle()
|
||||
} label: {
|
||||
DurationView(time: viewModel.observableRecipeDetail.prepTime, title: LocalizedStringKey("Preparation"))
|
||||
}
|
||||
Button {
|
||||
presentPopover.toggle()
|
||||
} label: {
|
||||
DurationView(time: viewModel.observableRecipeDetail.cookTime, title: LocalizedStringKey("Cooking"))
|
||||
}
|
||||
Button {
|
||||
presentPopover.toggle()
|
||||
} label: {
|
||||
DurationView(time: viewModel.observableRecipeDetail.totalTime, title: LocalizedStringKey("Total time"))
|
||||
}
|
||||
}
|
||||
.popover(isPresented: $presentPopover) {
|
||||
EditableDurationView(
|
||||
prepTime: viewModel.observableRecipeDetail.prepTime,
|
||||
cookTime: viewModel.observableRecipeDetail.cookTime,
|
||||
totalTime: viewModel.observableRecipeDetail.totalTime
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,48 +74,30 @@ fileprivate struct DurationView: View {
|
||||
}
|
||||
|
||||
fileprivate struct EditableDurationView: View {
|
||||
@ObservedObject var time: DurationComponents
|
||||
@State var title: LocalizedStringKey
|
||||
@State var presentPopoverView: Bool = false
|
||||
@State var hour: Int = 0
|
||||
@State var minute: Int = 0
|
||||
@ObservedObject var prepTime: DurationComponents
|
||||
@ObservedObject var cookTime: DurationComponents
|
||||
@ObservedObject var totalTime: DurationComponents
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
SecondaryLabel(text: title)
|
||||
Spacer()
|
||||
}
|
||||
Button {
|
||||
presentPopoverView.toggle()
|
||||
} label: {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Image(systemName: "clock")
|
||||
.foregroundStyle(.secondary)
|
||||
Text(time.displayString)
|
||||
.lineLimit(1)
|
||||
SecondaryLabel(text: "Preparation")
|
||||
Spacer()
|
||||
}
|
||||
TimePickerView(selectedHour: $prepTime.hourComponent, selectedMinute: $prepTime.minuteComponent)
|
||||
SecondaryLabel(text: "Cooking")
|
||||
TimePickerView(selectedHour: $cookTime.hourComponent, selectedMinute: $cookTime.minuteComponent)
|
||||
SecondaryLabel(text: "Total")
|
||||
TimePickerView(selectedHour: $totalTime.hourComponent, selectedMinute: $totalTime.minuteComponent)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.popover(isPresented: $presentPopoverView) {
|
||||
TimePickerPopoverView(selectedHour: $hour, selectedMinute: $minute)
|
||||
}
|
||||
.onChange(of: presentPopoverView) { presentPopover in
|
||||
if !presentPopover {
|
||||
time.hourComponent = String(hour)
|
||||
time.minuteComponent = String(minute)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
minute = Int(time.minuteComponent) ?? 0
|
||||
hour = Int(time.hourComponent) ?? 0
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fileprivate struct TimePickerPopoverView: View {
|
||||
fileprivate struct TimePickerView: View {
|
||||
@Binding var selectedHour: Int
|
||||
@Binding var selectedMinute: Int
|
||||
|
||||
|
||||
@@ -14,14 +14,19 @@ struct RecipeMetadataSection: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@ObservedObject var viewModel: RecipeView.ViewModel
|
||||
|
||||
@State var categories: [String] = []
|
||||
@State var keywords: [RecipeKeyword] = []
|
||||
var categories: [String] {
|
||||
appState.categories.map({ category in category.name })
|
||||
}
|
||||
|
||||
|
||||
@State var presentKeywordSheet: Bool = false
|
||||
@State var presentServingsPopover: Bool = false
|
||||
@State var presentCategoryPopover: Bool = false
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
// Category
|
||||
//CategoryPickerView(items: $categories, input: $viewModel.observableRecipeDetail.recipeCategory, titleKey: "Category")
|
||||
SecondaryLabel(text: "Category")
|
||||
HStack {
|
||||
@@ -29,13 +34,16 @@ struct RecipeMetadataSection: View {
|
||||
.lineLimit(1)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
Button {
|
||||
presentCategoryPopover.toggle()
|
||||
} label: {
|
||||
Text("Choose")
|
||||
Picker("Choose", selection: $viewModel.observableRecipeDetail.recipeCategory) {
|
||||
Text("").tag("")
|
||||
ForEach(categories, id: \.self) { item in
|
||||
Text(item)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.menu)
|
||||
}
|
||||
|
||||
// Keywords
|
||||
SecondaryLabel(text: "Keywords")
|
||||
|
||||
if !viewModel.observableRecipeDetail.keywords.isEmpty {
|
||||
@@ -54,7 +62,7 @@ struct RecipeMetadataSection: View {
|
||||
Image(systemName: "chevron.right")
|
||||
}
|
||||
|
||||
|
||||
// Servings / Yield
|
||||
VStack(alignment: .leading) {
|
||||
SecondaryLabel(text: "Servings")
|
||||
Button {
|
||||
@@ -63,22 +71,16 @@ struct RecipeMetadataSection: View {
|
||||
Text("\(viewModel.observableRecipeDetail.recipeYield) serving(s)")
|
||||
.lineLimit(1)
|
||||
}
|
||||
.popover(isPresented: $presentServingsPopover) {
|
||||
PickerPopoverView(value: $viewModel.observableRecipeDetail.recipeYield, items: 0..<99, titleKey: "Servings")
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(Rectangle().foregroundStyle(Color.white.opacity(0.1)))
|
||||
.task {
|
||||
categories = appState.categories.map({ category in category.name })
|
||||
}
|
||||
.sheet(isPresented: $presentKeywordSheet) {
|
||||
KeywordPickerView(title: "Keywords", searchSuggestions: appState.allKeywords, selection: $viewModel.observableRecipeDetail.keywords)
|
||||
}
|
||||
.popover(isPresented: $presentServingsPopover) {
|
||||
PickerPopoverView(value: $viewModel.observableRecipeDetail.recipeYield, items: 0..<99, titleKey: "Servings")
|
||||
}
|
||||
.popover(isPresented: $presentCategoryPopover) {
|
||||
PickerPopoverView(value: $viewModel.observableRecipeDetail.recipeCategory, items: categories, titleKey: "Category")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +97,7 @@ fileprivate struct PickerPopoverView<Item: Hashable & CustomStringConvertible, C
|
||||
}
|
||||
}
|
||||
.pickerStyle(WheelPickerStyle())
|
||||
.frame(width: 100, height: 150)
|
||||
.frame(width: 150, height: 150)
|
||||
.clipped()
|
||||
}
|
||||
.padding()
|
||||
|
||||
Reference in New Issue
Block a user