Add lead workflows, PDF signing, AR projects and photo gallery integration
This commit is contained in:
68
GasTankAR/Data/Leads/DefaultLeadRepository.swift
Normal file
68
GasTankAR/Data/Leads/DefaultLeadRepository.swift
Normal file
@ -0,0 +1,68 @@
|
||||
import Foundation
|
||||
|
||||
struct DefaultLeadRepository: LeadRepository {
|
||||
let remoteService: any LeadRemoteService
|
||||
|
||||
func leads(for salesCode: String, query: LeadQuery) async throws -> [Lead] {
|
||||
do {
|
||||
let values = try await remoteService.fetchLeads(salesCode: salesCode, query: query)
|
||||
let leads = try values.map { try $0.toDomain() }
|
||||
guard Set(leads.map(\.id)).count == leads.count else {
|
||||
throw LeadError.invalidResponse
|
||||
}
|
||||
return leads
|
||||
} catch {
|
||||
throw Self.map(error)
|
||||
}
|
||||
}
|
||||
|
||||
func lead(id: String, salesCode: String) async throws -> Lead {
|
||||
do {
|
||||
let value = try await remoteService.fetchLead(id: id, salesCode: salesCode)
|
||||
guard value.id == id else { throw LeadError.invalidResponse }
|
||||
return try value.toDomain()
|
||||
} catch {
|
||||
throw Self.map(error, leadID: id)
|
||||
}
|
||||
}
|
||||
|
||||
func setBookmark(_ bookmarked: Bool, leadID: String, salesCode: String) async throws -> Lead {
|
||||
do {
|
||||
let value = try await remoteService.setBookmark(bookmarked, id: leadID, salesCode: salesCode)
|
||||
guard value.id == leadID, value.isBookmarked == bookmarked else {
|
||||
throw LeadError.invalidResponse
|
||||
}
|
||||
return try value.toDomain()
|
||||
} catch {
|
||||
throw Self.map(error, leadID: leadID)
|
||||
}
|
||||
}
|
||||
|
||||
static func map(_ error: Error, leadID: String? = nil) -> Error {
|
||||
if error is CancellationError { return CancellationError() }
|
||||
if let error = error as? LeadError { return error }
|
||||
if let error = error as? URLError {
|
||||
switch error.code {
|
||||
case .cancelled: return CancellationError()
|
||||
case .notConnectedToInternet, .networkConnectionLost: return LeadError.offline
|
||||
case .timedOut: return LeadError.timeout
|
||||
case .cannotFindHost, .cannotConnectToHost, .dnsLookupFailed:
|
||||
return LeadError.serviceUnavailable
|
||||
default: return LeadError.unexpected
|
||||
}
|
||||
}
|
||||
if let error = error as? LeadRemoteError {
|
||||
switch error {
|
||||
case .http(401): return LeadError.unauthorized
|
||||
case .http(403): return LeadError.forbidden
|
||||
case .http(404):
|
||||
return leadID.map { LeadError.notFound(leadID: $0) } ?? .serviceUnavailable
|
||||
case .http(let status) where status >= 500: return LeadError.serviceUnavailable
|
||||
case .malformedResponse: return LeadError.invalidResponse
|
||||
default: return LeadError.unexpected
|
||||
}
|
||||
}
|
||||
if error is DecodingError { return LeadError.invalidResponse }
|
||||
return LeadError.unexpected
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user