InvestmentTrackerApp/PortfolioJournal/Repositories/GoalRepository.swift

113 lines
2.9 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 {
self.goals = try self.context.fetch(request)
} catch {
print("Failed to fetch goals: \(error)")
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)")
}
}
}