InvestmentTrackerApp/PortfolioJournal/Views/Settings/AllocationTargetsView.swift

91 lines
3.0 KiB
Swift

import SwiftUI
struct AllocationTargetsView: View {
@StateObject private var categoryRepository = CategoryRepository()
@State private var targetValues: [UUID: String] = [:]
var body: some View {
List {
Section {
HStack {
Text("Total Targets")
Spacer()
Text(String(format: "%.0f%%", totalTargets))
.foregroundColor(totalTargets == 100 ? .positiveGreen : .secondary)
}
if totalTargets != 100 {
Text("Targets don't need to be perfect, but aiming for 100% keeps the drift view accurate.")
.font(.caption)
.foregroundColor(.secondary)
}
}
Section {
ForEach(categoryRepository.categories) { category in
let categoryId = category.id
HStack {
HStack(spacing: 8) {
Circle()
.fill(category.color)
.frame(width: 10, height: 10)
Text(category.name)
}
Spacer()
TextField("0", text: targetBinding(for: categoryId))
.keyboardType(.decimalPad)
.multilineTextAlignment(.trailing)
.frame(width: 60)
Text("%")
.foregroundColor(.secondary)
}
}
} header: {
Text("Targets by Category")
} footer: {
Text("Set your desired allocation percentages to track drift over time.")
}
}
.navigationTitle("Allocation Targets")
.navigationBarTitleDisplayMode(.inline)
.onAppear {
preloadTargets()
}
}
private var totalTargets: Double {
let ids = categoryRepository.categories.compactMap { $0.id }
return AllocationTargetStore.totalTargetPercentage(for: ids)
}
private func preloadTargets() {
targetValues = categoryRepository.categories.reduce(into: [:]) { result, category in
let id = category.id
if let target = AllocationTargetStore.target(for: id) {
result[id] = String(format: "%.0f", target)
}
}
}
private func targetBinding(for categoryId: UUID) -> Binding<String> {
Binding(
get: { targetValues[categoryId] ?? "" },
set: { newValue in
targetValues[categoryId] = newValue
let sanitized = newValue.replacingOccurrences(of: ",", with: ".")
let value = Double(sanitized) ?? 0
AllocationTargetStore.setTarget(value, for: categoryId)
}
)
}
}
#Preview {
NavigationStack {
AllocationTargetsView()
}
}