import SwiftUI struct ARProjectCreateView: View { let isEditing: Bool let onCreate: (String, Tank, Bool) -> Void @State private var name = "" @State private var tank = Tank() @Environment(\.tankCatalog) private var catalog init(project: ARProject? = nil, onCreate: @escaping (String, Tank, Bool) -> Void) { isEditing = project != nil self.onCreate = onCreate _name = State(initialValue: project?.name ?? "") _tank = State(initialValue: project?.tank ?? Tank()) } private var canCreate: Bool { !name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && catalog.definition(for: tank) != nil } var body: some View { Form { Section { VStack(spacing: 8) { ARProjectTankImage(tank: tank) .frame(height: 150) .frame(maxWidth: .infinity) Text("\(tank.size.volumeTitle) · \(tank.placement.displayName) · \(catalog.displayName(for: tank.color))") .font(.subheadline).foregroundStyle(.secondary) } .padding(.vertical, 8) } Section("Name") { TextField("Projektname", text: $name) .textInputAutocapitalization(.sentences) } Section("Tankkonfiguration") { ARProjectConfigurationView(tank: $tank) } } .navigationTitle(isEditing ? "Projekt bearbeiten" : "Neues Projekt") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .confirmationAction) { Button(isEditing ? "Speichern" : "Anlegen") { onCreate(name, tank, false) } .disabled(!canCreate) } } .safeAreaInset(edge: .bottom) { Button { onCreate(name, tank, true) } label: { Label(isEditing ? "Speichern und AR-Modus starten" : "Anlegen und AR-Modus starten", systemImage: "arkit") .font(.headline).frame(maxWidth: .infinity).padding(.vertical, 10) } .buttonStyle(.borderedProminent) .disabled(!canCreate) .padding() .background(.bar) } .onAppear { tank = catalog.normalized(tank) } } } struct ARProjectConfigurationView: View { @Binding var tank: Tank @Environment(\.tankCatalog) private var catalog var body: some View { VStack(alignment: .leading, spacing: 10) { Text("Volumen").font(.subheadline) Picker("Volumen", selection: $tank.size) { ForEach(catalog.sizes(for: tank.placement)) { size in Text(size.volumeTitle).tag(size) } } .pickerStyle(.segmented) } .padding(.vertical, 4) VStack(alignment: .leading, spacing: 10) { Text("Aufstellung").font(.subheadline) Picker("Aufstellung", selection: $tank.placement) { ForEach(catalog.placements) { placement in Text(placement.displayName).tag(placement) } } .pickerStyle(.segmented) } .padding(.vertical, 4) HStack { Text("Farbe") Spacer() ForEach(catalog.colors(for: tank.size, placement: tank.placement)) { color in Button { tank.color = color } label: { Circle().fill(swatch(color)) .frame(width: 28, height: 28) .overlay { Circle().strokeBorder(.gray.opacity(0.5), lineWidth: 1) } .padding(4) .overlay { Circle().strokeBorder(tank.color == color ? Color.accentColor : .clear, lineWidth: 2) } .frame(minWidth: 44, minHeight: 44) } .buttonStyle(.plain) .accessibilityLabel(catalog.displayName(for: color)) .accessibilityAddTraits(tank.color == color ? .isSelected : []) } Text(catalog.displayName(for: tank.color)).foregroundStyle(.secondary).font(.subheadline) } .onChange(of: tank.placement) { _, _ in normalize() } .onChange(of: tank.size) { _, _ in normalize() } } private func normalize() { tank = catalog.normalized(tank) tank.showLidOnly = false } private func swatch(_ color: TankColor) -> Color { switch color { case .white: .white case .green: Color(red: 0.49, green: 0.65, blue: 0.42) case .olive: Color(red: 0.37, green: 0.40, blue: 0.22) } } } #Preview("Projekt konfigurieren") { NavigationStack { ARProjectCreateView { _, _, _ in } } .frame(width: 600, height: 760) } #Preview("Projekt konfigurieren – Dunkel") { NavigationStack { ARProjectCreateView { _, _, _ in } } .frame(width: 600, height: 760) .preferredColorScheme(.dark) }