initial version
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user