// // DocuframeView.swift // GasTankAR // // Created by Dennis Nemec on 28.08.26. // import SwiftUI import SwiftData /// DOCUframe-Tab: Auswahl aufgenommener Fotos und Übergabe an DOCUframe (Upload) bzw. Mailversand. struct DocuframeView: View { let project: Project @State private var viewModel = DocuframeViewModel() private let columns = [GridItem(.adaptive(minimum: 110), spacing: 2)] private var photos: [ProjectPhoto] { project.photos.sorted { $0.creationDate > $1.creationDate } } var body: some View { Group { if photos.isEmpty { ContentUnavailableView( "Keine Fotos", systemImage: "photo.on.rectangle.angled", description: Text("Nimm im AR-Modus Fotos auf, um sie an DOCUframe zu übergeben.") ) } else { ScrollView { LazyVGrid(columns: columns, spacing: 2) { ForEach(photos) { photo in selectableThumbnail(photo) } } .padding(2) } } } .safeAreaInset(edge: .bottom) { if !photos.isEmpty { actionBar } } .alert( viewModel.result?.title ?? "", isPresented: resultBinding, presenting: viewModel.result ) { _ in Button("OK", role: .cancel) {} } message: { result in Text(result.message) } } private func selectableThumbnail(_ photo: ProjectPhoto) -> some View { let selected = viewModel.isSelected(photo) return PhotoThumbnail(imageData: photo.imageData) .aspectRatio(1, contentMode: .fit) .clipped() .overlay(alignment: .topTrailing) { Image(systemName: selected ? "checkmark.circle.fill" : "circle") .font(.title3) .symbolRenderingMode(.palette) .foregroundStyle(.white, selected ? Color.accentColor : Color.black.opacity(0.35)) .padding(6) .shadow(radius: 2) } .overlay { if selected { Rectangle().strokeBorder(Color.accentColor, lineWidth: 3) } } .contentShape(.rect) .onTapGesture { viewModel.toggleSelection(photo) } } private var actionBar: some View { VStack(spacing: 10) { Text(viewModel.hasSelection ? "\(viewModel.selectionCount) ausgewählt" : "Fotos zum Übertragen auswählen") .font(.footnote) .foregroundStyle(.secondary) VStack(spacing: 8) { Button { Task { await viewModel.upload(from: photos, leadID: project.leadID) } } label: { Label("In DOCUframe hochladen", systemImage: "arrow.up.doc") .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) Button { Task { await viewModel.sendEmail(from: photos, leadID: project.leadID) } } label: { Label("E-Mail senden", systemImage: "envelope") .frame(maxWidth: .infinity) } .buttonStyle(.bordered) } .controlSize(.large) .disabled(!viewModel.hasSelection || viewModel.isProcessing) if viewModel.isProcessing { ProgressView() } } .padding() .background(.bar) } private var resultBinding: Binding { Binding( get: { viewModel.result != nil }, set: { if !$0 { viewModel.result = nil } } ) } } #Preview { let sample = PreviewSupport.galleryProjectContainer() return NavigationStack { DocuframeView(project: sample.project) } .modelContainer(sample.container) }