Files
2025-05-31 11:12:14 +02:00

148 lines
4.8 KiB
Swift

//
// RecipeDurationSection.swift
// Nextcloud Cookbook iOS Client
//
// Created by Vincent Meilinger on 01.03.24.
//
import Foundation
import SwiftUI
// MARK: - RecipeView Duration Section
struct RecipeDurationSection: View {
@Bindable var recipe: Recipe
@Binding var editMode: Bool
@State var presentPopover: Bool = false
var body: some View {
VStack(alignment: .leading) {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 200, maximum: .infinity), alignment: .leading)]) {
DurationView(time: recipe.prepTimeDurationComponent, title: LocalizedStringKey("Preparation"))
DurationView(time: recipe.cookTimeDurationComponent, title: LocalizedStringKey("Cooking"))
DurationView(time: recipe.totalTimeDurationComponent, title: LocalizedStringKey("Total time"))
}
if editMode {
Button {
presentPopover.toggle()
} label: {
Text("Edit")
}
.buttonStyle(.borderedProminent)
.padding(.top, 5)
}
}
.padding()
.popover(isPresented: $presentPopover) {
EditableDurationView(
prepTime: recipe.prepTimeDurationComponent,
cookTime: recipe.cookTimeDurationComponent,
totalTime: recipe.totalTimeDurationComponent
)
}
}
}
fileprivate struct DurationView: View {
@ObservedObject var time: DurationComponents
@State var title: LocalizedStringKey
var body: some View {
VStack(alignment: .leading) {
HStack {
SecondaryLabel(text: title)
Spacer()
}
HStack {
Image(systemName: "clock")
.bold()
.foregroundStyle(.secondary)
Text(time.displayString)
.lineLimit(1)
}
}
}
}
fileprivate struct EditableDurationView: View {
@Environment(\.presentationMode) var presentationMode
@ObservedObject var prepTime: DurationComponents
@ObservedObject var cookTime: DurationComponents
@ObservedObject var totalTime: DurationComponents
var body: some View {
ScrollView {
VStack(alignment: .center) {
HStack {
SecondaryLabel(text: "Preparation")
Spacer()
Button("Done") {
presentationMode.wrappedValue.dismiss()
}
}
TimePickerView(selectedHour: $prepTime.hourComponent, selectedMinute: $prepTime.minuteComponent)
HStack {
SecondaryLabel(text: "Cooking")
Spacer()
}
TimePickerView(selectedHour: $cookTime.hourComponent, selectedMinute: $cookTime.minuteComponent)
HStack {
SecondaryLabel(text: "Total time")
Spacer()
}
TimePickerView(selectedHour: $totalTime.hourComponent, selectedMinute: $totalTime.minuteComponent)
}
.padding()
.onChange(of: prepTime.hourComponent) { updateTotalTime() }
.onChange(of: prepTime.minuteComponent) { updateTotalTime() }
.onChange(of: cookTime.hourComponent) { updateTotalTime() }
.onChange(of: cookTime.minuteComponent) { updateTotalTime() }
}
}
private func updateTotalTime() {
var hourComponent = prepTime.hourComponent + cookTime.hourComponent
var minuteComponent = prepTime.minuteComponent + cookTime.minuteComponent
// Handle potential overflow from minutes to hours
if minuteComponent >= 60 {
hourComponent += minuteComponent / 60
minuteComponent %= 60
}
totalTime.hourComponent = hourComponent
totalTime.minuteComponent = minuteComponent
}
}
fileprivate struct TimePickerView: View {
@Binding var selectedHour: Int
@Binding var selectedMinute: Int
var body: some View {
HStack {
Picker(selection: $selectedHour, label: Text("Hours")) {
ForEach(0..<99, id: \.self) { hour in
Text("\(hour) h").tag(hour)
}
}
.pickerStyle(WheelPickerStyle())
.frame(width: 100, height: 150)
.clipped()
Picker(selection: $selectedMinute, label: Text("Minutes")) {
ForEach(0..<60, id: \.self) { minute in
Text("\(minute) min").tag(minute)
}
}
.pickerStyle(WheelPickerStyle())
.frame(width: 100, height: 150)
.clipped()
}
.padding()
}
}