Add lead workflows, PDF signing, AR projects and photo gallery integration
This commit is contained in:
106
GasTankAR/Views/Leads/Detail/LeadDetailViewModel.swift
Normal file
106
GasTankAR/Views/Leads/Detail/LeadDetailViewModel.swift
Normal file
@ -0,0 +1,106 @@
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
final class LeadDetailViewModel {
|
||||
private(set) var detail: LeadDetail?
|
||||
private(set) var error: LeadError?
|
||||
var expandedOffers: Set<String> = []
|
||||
var expandedGroups: Set<String> = []
|
||||
var selectedDocument: LeadDocument?
|
||||
var signingRequest: LeadSigningRequest?
|
||||
private(set) var signedDocumentURLs: [String: URL] = [:]
|
||||
private let leadID: String
|
||||
private let salesCode: String
|
||||
private let getDetail: GetLeadDetailUseCase
|
||||
private var generation = 0
|
||||
|
||||
init(leadID: String, salesCode: String, repository: any LeadDetailRepository) {
|
||||
self.leadID = leadID
|
||||
self.salesCode = salesCode
|
||||
self.getDetail = GetLeadDetailUseCase(repository: repository)
|
||||
}
|
||||
|
||||
var lead: Lead? { detail?.lead }
|
||||
var isAllExpanded: Bool {
|
||||
guard let detail, !detail.offers.isEmpty else { return false }
|
||||
return Set(detail.offers.map(\.id)).isSubset(of: expandedOffers)
|
||||
&& Set(detail.offers.flatMap(\.groups).map(\.id)).isSubset(of: expandedGroups)
|
||||
}
|
||||
|
||||
func load() async {
|
||||
generation += 1
|
||||
let request = generation
|
||||
detail = nil
|
||||
error = nil
|
||||
do {
|
||||
let result = try await getDetail.execute(id: leadID, salesCode: salesCode)
|
||||
try Task.checkCancellation()
|
||||
guard request == generation else { return }
|
||||
detail = result
|
||||
let documents = result.offers.flatMap(\.documents)
|
||||
signedDocumentURLs = LeadSignedDocumentStore().savedURLs(
|
||||
documents: documents, leadID: leadID, salesCode: salesCode
|
||||
)
|
||||
for document in documents {
|
||||
if let url = signedDocumentURLs[document.id] { didSign(document, url: url) }
|
||||
}
|
||||
if let first = result.offers.first {
|
||||
expandedOffers = [first.id]
|
||||
expandedGroups = Set(first.groups.filter { !$0.isComplete }.map(\.id))
|
||||
} else {
|
||||
expandedOffers = []
|
||||
expandedGroups = []
|
||||
}
|
||||
} catch is CancellationError {
|
||||
} catch {
|
||||
guard request == generation, !Task.isCancelled else { return }
|
||||
self.error = error as? LeadError ?? .unexpected
|
||||
}
|
||||
}
|
||||
|
||||
func startSigning(offer: LeadOffer, group: LeadDocumentGroup? = nil) {
|
||||
let documents = group?.documents ?? offer.documents
|
||||
guard documents.contains(where: { $0.status == .pending }) else { return }
|
||||
signingRequest = LeadSigningRequest(
|
||||
offerID: offer.id,
|
||||
signerName: detail?.contactName ?? detail?.lead.displayName ?? "Kunde",
|
||||
documents: documents
|
||||
)
|
||||
}
|
||||
|
||||
func didSign(_ document: LeadDocument, url: URL) {
|
||||
signedDocumentURLs[document.id] = url
|
||||
guard var detail else { return }
|
||||
for offerIndex in detail.offers.indices {
|
||||
for groupIndex in detail.offers[offerIndex].groups.indices {
|
||||
for documentIndex in detail.offers[offerIndex].groups[groupIndex].documents.indices {
|
||||
if detail.offers[offerIndex].groups[groupIndex].documents[documentIndex].id == document.id {
|
||||
detail.offers[offerIndex].groups[groupIndex].documents[documentIndex].status = .signed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.detail = detail
|
||||
}
|
||||
|
||||
func toggleOffer(_ id: String) {
|
||||
if !expandedOffers.insert(id).inserted { expandedOffers.remove(id) }
|
||||
}
|
||||
|
||||
func toggleGroup(_ id: String) {
|
||||
if !expandedGroups.insert(id).inserted { expandedGroups.remove(id) }
|
||||
}
|
||||
|
||||
func toggleAll() {
|
||||
guard let detail else { return }
|
||||
if isAllExpanded {
|
||||
expandedOffers = []
|
||||
expandedGroups = []
|
||||
} else {
|
||||
expandedOffers = Set(detail.offers.map(\.id))
|
||||
expandedGroups = Set(detail.offers.flatMap(\.groups).map(\.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user