50 lines
1.8 KiB
Swift
50 lines
1.8 KiB
Swift
import Foundation
|
|
import UIKit
|
|
|
|
/// Drives the "Beleg scannen" flow: takes a captured/picked `UIImage`,
|
|
/// uploads it to `POST /api/scan` for AI extraction, and hands the resulting
|
|
/// `Receipt` back to the view. Does NOT persist anything itself — saving
|
|
/// happens later in `ReceiptReviewView` via `ReceiptsAPI.sync(...)`.
|
|
@MainActor
|
|
final class ScanViewModel: ObservableObject {
|
|
@Published var isUploading = false
|
|
@Published var errorMessage: String?
|
|
|
|
/// Converts the image to JPEG and uploads it for extraction.
|
|
/// Returns the extracted `Receipt` on success, or `nil` on failure
|
|
/// (in which case `errorMessage` is set to German user-facing text).
|
|
func uploadAndExtract(image: UIImage) async -> Receipt? {
|
|
guard let data = image.jpegData(compressionQuality: 0.85) else {
|
|
errorMessage = "Bild konnte nicht verarbeitet werden."
|
|
return nil
|
|
}
|
|
return await uploadAndExtract(imageData: data)
|
|
}
|
|
|
|
/// Same as above, but takes already-encoded JPEG data directly.
|
|
func uploadAndExtract(imageData: Data) async -> Receipt? {
|
|
isUploading = true
|
|
errorMessage = nil
|
|
defer { isUploading = false }
|
|
|
|
do {
|
|
let response = try await ReceiptsAPI.scan(
|
|
fileData: imageData,
|
|
fileName: "receipt.jpg",
|
|
mimeType: "image/jpeg"
|
|
)
|
|
guard let receipt = response.receipt else {
|
|
errorMessage = "Es konnten keine Belegdaten erkannt werden."
|
|
return nil
|
|
}
|
|
return receipt
|
|
} catch let error as APIError {
|
|
errorMessage = error.localizedDescription
|
|
return nil
|
|
} catch {
|
|
errorMessage = error.localizedDescription
|
|
return nil
|
|
}
|
|
}
|
|
}
|