91 lines
3.0 KiB
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()
|
|
}
|
|
}
|