7a18dd8360
- 151: contribución editable por snapshot en cualquier modo (quitado gate detailed) con diálogo de propagación al editar: solo este / adelante / atrás / todos (SnapshotRepository.propagateContribution, SnapshotFormViewModel.contributionChanged) - 148: Period vs Period mostraba mal el último mes del period B — la agrupación usaba chartMonth(for:) que aplicaba el grace-period del check-in a snapshots históricos; ahora agrupa por mes calendario crudo - 152: iPad Sources no saltaba entre fuentes — añadido .id() al SourceDetailView para recrear el StateObject al cambiar de selección - 146/147: Year vs Year con forecast del año en curso (asterisco de estimado) y KPIs arriba / detalle debajo - 145: card de contribución mensual en SourceDetailView - Nuevas claves snapshot_contribution_propagate_* en los 7 idiomas Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015qUZrBusG82T37R7PeokqJ
34 lines
1.1 KiB
Swift
34 lines
1.1 KiB
Swift
import Foundation
|
|
|
|
enum MonthlyContributionStore {
|
|
private static let key = "monthlyContributions"
|
|
|
|
static func contribution(for sourceId: UUID) -> Decimal? {
|
|
let dict = load()
|
|
guard let raw = dict[sourceId.uuidString] else { return nil }
|
|
return Decimal(raw)
|
|
}
|
|
|
|
static func setContribution(_ amount: Decimal?, for sourceId: UUID) {
|
|
var dict = load()
|
|
if let amount, amount > 0 {
|
|
dict[sourceId.uuidString] = NSDecimalNumber(decimal: amount).doubleValue
|
|
} else {
|
|
dict.removeValue(forKey: sourceId.uuidString)
|
|
}
|
|
save(dict)
|
|
}
|
|
|
|
private static func load() -> [String: Double] {
|
|
guard let data = UserDefaults.standard.data(forKey: key),
|
|
let decoded = try? JSONDecoder().decode([String: Double].self, from: data) else { return [:] }
|
|
return decoded
|
|
}
|
|
|
|
private static func save(_ dict: [String: Double]) {
|
|
if let data = try? JSONEncoder().encode(dict) {
|
|
UserDefaults.standard.set(data, forKey: key)
|
|
}
|
|
}
|
|
}
|