118 lines
3.0 KiB
Swift
118 lines
3.0 KiB
Swift
import Foundation
|
|
import CoreData
|
|
import Combine
|
|
|
|
class GoalRepository: ObservableObject {
|
|
private let context: NSManagedObjectContext
|
|
|
|
@Published private(set) var goals: [Goal] = []
|
|
|
|
init(context: NSManagedObjectContext = CoreDataStack.shared.viewContext) {
|
|
self.context = context
|
|
fetchGoals()
|
|
setupNotificationObserver()
|
|
}
|
|
|
|
private func setupNotificationObserver() {
|
|
NotificationCenter.default.addObserver(
|
|
self,
|
|
selector: #selector(contextDidChange),
|
|
name: .NSManagedObjectContextObjectsDidChange,
|
|
object: context
|
|
)
|
|
}
|
|
|
|
@objc private func contextDidChange(_ notification: Notification) {
|
|
fetchGoals()
|
|
}
|
|
|
|
// MARK: - Fetch
|
|
|
|
func fetchGoals(for account: Account? = nil) {
|
|
context.perform { [weak self] in
|
|
guard let self else { return }
|
|
let request: NSFetchRequest<Goal> = Goal.fetchRequest()
|
|
if let account = account {
|
|
request.predicate = NSPredicate(format: "account == %@", account)
|
|
}
|
|
request.sortDescriptors = [
|
|
NSSortDescriptor(keyPath: \Goal.createdAt, ascending: true)
|
|
]
|
|
|
|
do {
|
|
let fetched = try self.context.fetch(request)
|
|
DispatchQueue.main.async {
|
|
self.goals = fetched
|
|
}
|
|
} catch {
|
|
print("Failed to fetch goals: \(error)")
|
|
DispatchQueue.main.async {
|
|
self.goals = []
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Create
|
|
|
|
@discardableResult
|
|
func createGoal(
|
|
name: String,
|
|
targetAmount: Decimal,
|
|
targetDate: Date? = nil,
|
|
account: Account?
|
|
) -> Goal {
|
|
let goal = Goal(context: context)
|
|
goal.name = name
|
|
goal.targetAmount = NSDecimalNumber(decimal: targetAmount)
|
|
goal.targetDate = targetDate
|
|
goal.account = account
|
|
save()
|
|
return goal
|
|
}
|
|
|
|
// MARK: - Update
|
|
|
|
func updateGoal(
|
|
_ goal: Goal,
|
|
name: String? = nil,
|
|
targetAmount: Decimal? = nil,
|
|
targetDate: Date? = nil,
|
|
clearTargetDate: Bool = false,
|
|
isActive: Bool? = nil
|
|
) {
|
|
if let name = name {
|
|
goal.name = name
|
|
}
|
|
if let targetAmount = targetAmount {
|
|
goal.targetAmount = NSDecimalNumber(decimal: targetAmount)
|
|
}
|
|
if clearTargetDate {
|
|
goal.targetDate = nil
|
|
} else if let targetDate = targetDate {
|
|
goal.targetDate = targetDate
|
|
}
|
|
if let isActive = isActive {
|
|
goal.isActive = isActive
|
|
}
|
|
save()
|
|
}
|
|
|
|
func deleteGoal(_ goal: Goal) {
|
|
context.delete(goal)
|
|
save()
|
|
}
|
|
|
|
// MARK: - Save
|
|
|
|
private func save() {
|
|
guard context.hasChanges else { return }
|
|
do {
|
|
try context.save()
|
|
fetchGoals()
|
|
} catch {
|
|
print("Failed to save goals: \(error)")
|
|
}
|
|
}
|
|
}
|