Add lead workflows, PDF signing, AR projects and photo gallery integration
This commit is contained in:
140
GasTankAR/Views/AR/Projects/ARProjectCreateView.swift
Normal file
140
GasTankAR/Views/AR/Projects/ARProjectCreateView.swift
Normal file
@ -0,0 +1,140 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user