Add lead workflows, PDF signing, AR projects and photo gallery integration

This commit is contained in:
Dennis Nemec
2026-11-08 17:49:39 +01:00
parent a343bde741
commit 8d18873412
82 changed files with 6401 additions and 34 deletions

View File

@ -0,0 +1,98 @@
import SwiftUI
import SwiftData
struct LeadDetailScreen: View {
@State private var model: LeadDetailViewModel
@State private var retryID = 0
@Environment(\.dismiss) private var dismiss
private let leadID: String
private let salesCode: String
private let repository: any LeadDetailRepository
let onLogout: () -> Void
init(leadID: String, salesCode: String, repository: any LeadDetailRepository,
onLogout: @escaping () -> Void) {
self.leadID = leadID
self.salesCode = salesCode
self.repository = repository
_model = State(initialValue: LeadDetailViewModel(
leadID: leadID, salesCode: salesCode, repository: repository
))
self.onLogout = onLogout
}
var body: some View {
@Bindable var model = model
ZStack {
if let error = model.error {
ContentUnavailableView {
Label("Interessent konnte nicht geladen werden", systemImage: "exclamationmark.triangle")
} description: {
Text(error.message)
} actions: {
if error == .unauthorized {
Button("Erneut anmelden", action: onLogout)
} else if error.allowsRetry {
Button("Erneut versuchen") { retryID += 1 }
}
Button("Zur Übersicht") { dismiss() }
}
} else if let detail = model.detail {
LeadDetailView(detail: detail, model: model, salesCode: salesCode,
repository: repository, onLogout: onLogout)
} else {
LeadDetailSkeletonView()
}
}
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.tint(LeadDetailStyle.blue)
.toolbar {
ToolbarItem(placement: .principal) {
HStack(spacing: 8) {
Image("LoginLogo")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
.clipShape(.rect(cornerRadius: 8))
.accessibilityHidden(true)
Text("DrachenGas")
.font(.headline)
.foregroundStyle(LeadDetailStyle.blue)
}
.accessibilityElement(children: .combine)
}
if model.detail == nil && model.error == nil {
ToolbarItem(placement: .topBarTrailing) {
ProgressView().accessibilityLabel("Interessent wird geladen")
}
}
}
.sheet(item: $model.selectedDocument) { document in
LeadPDFPreview(document: document, leadID: leadID, salesCode: salesCode,
repository: repository, onLogout: onLogout,
signedURL: model.signedDocumentURLs[document.id])
}
.sheet(item: $model.signingRequest) { request in
LeadSigningSheet(request: request, leadID: leadID, salesCode: salesCode,
repository: repository, onSigned: model.didSign)
}
.modelContainer(for: [Project.self, LeadARProjectLink.self])
.task(id: retryID) { await model.load() }
}
}
#Preview("Interessent", traits: .fixedLayout(width: 1194, height: 834)) {
NavigationStack {
LeadDetailScreen(leadID: "L-240318", salesCode: "MKR",
repository: DefaultLeadDetailRepository(
remoteService: StubLeadDetailRemoteService(delay: .zero)),
onLogout: {})
}
}
#Preview("Ladezustand", traits: .fixedLayout(width: 1194, height: 834)) {
NavigationStack {
LeadDetailSkeletonView().navigationTitle("")
}
}