Files
bulkhealth/BulkHealthApp/Import/ImportFlowViewModel.swift

96 lines
2.8 KiB
Swift

import Foundation
import SwiftUI
import UniformTypeIdentifiers
@MainActor
final class ImportFlowViewModel: ObservableObject {
@Published var template = MoodwellStateOfMindTemplate.template
@Published var entries: [MoodwellEntry] = []
@Published var sourceKeys: [String] = []
@Published var mapping = MoodwellStateOfMindTemplate.defaultMapping
@Published var moodValenceScale: [Int: Double] = [1: -0.8, 2: -0.25, 3: 0.3, 4: 0.8]
@Published var dryRunResult: DryRunResult?
@Published var isImporting = false
@Published var statusMessage = ""
@Published var errorMessage: String?
let supportedContentTypes: [UTType] = [.json]
private let healthKitService = HealthKitService()
init() {
loadBundledSample()
}
func loadBundledSample() {
guard let url = Bundle.main.url(forResource: "MoodwellData", withExtension: "json") else {
errorMessage = String(localized: "error.sample.missing")
return
}
loadFile(from: url)
}
func loadFile(from url: URL) {
do {
let data = try Data(contentsOf: url)
let payload = try JSONDecoder().decode(MoodwellPayload.self, from: data)
entries = payload.mymoods
if let firstEntry = payload.mymoods.first {
sourceKeys = Array(firstEntry.sourceDictionary.keys).sorted()
} else {
sourceKeys = []
}
dryRunResult = nil
statusMessage = String.localizedStringWithFormat(
NSLocalizedString("status.loaded", comment: ""),
entries.count
)
errorMessage = nil
} catch {
errorMessage = String(localized: "error.load.file") + " \(error.localizedDescription)"
}
}
func runDryRun() {
let result = MoodwellStateOfMindTemplate.makeDrafts(entries: entries, mapping: mapping, moodValenceScale: moodValenceScale)
dryRunResult = result
if result.errors.isEmpty {
statusMessage = String.localizedStringWithFormat(
NSLocalizedString("status.dryrun.success", comment: ""),
result.drafts.count
)
} else {
statusMessage = String.localizedStringWithFormat(
NSLocalizedString("status.dryrun.withErrors", comment: ""),
result.errors.count
)
}
}
func commitImport() async {
guard let dryRunResult else {
errorMessage = String(localized: "error.dryrun.required")
return
}
guard dryRunResult.errors.isEmpty else {
errorMessage = String(localized: "error.dryrun.fix")
return
}
isImporting = true
defer { isImporting = false }
do {
try await healthKitService.requestWriteAccessForStateOfMind()
try await healthKitService.save(dryRunResult.drafts)
statusMessage = String.localizedStringWithFormat(
NSLocalizedString("status.import.success", comment: ""),
dryRunResult.drafts.count
)
errorMessage = nil
} catch {
errorMessage = String(localized: "error.import.failed") + " \(error.localizedDescription)"
}
}
}