Fix compilation errors in ChartsViewModel and AllocationEvolutionChart

- Remove unnecessary optional binding for non-optional source.id
- Break up AllocationEvolutionChart body to help Swift type-checker

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
alexandrev-tibco
2026-02-12 00:04:52 +01:00
parent 151eb0e662
commit ace58e5b0f
2 changed files with 57 additions and 32 deletions
@@ -294,8 +294,7 @@ class ChartsViewModel: ObservableObject {
let sources: [InvestmentSource] let sources: [InvestmentSource]
if !selectedSourceIds.isEmpty { if !selectedSourceIds.isEmpty {
sources = sourceRepository.sources.filter { source in sources = sourceRepository.sources.filter { source in
guard let id = source.id else { return false } selectedSourceIds.contains(source.id) && shouldIncludeSource(source)
return selectedSourceIds.contains(id) && shouldIncludeSource(source)
} }
} else if let selectedSource { } else if let selectedSource {
sources = sourceRepository.sources.filter { $0.id == selectedSource.id && shouldIncludeSource($0) } sources = sourceRepository.sources.filter { $0.id == selectedSource.id && shouldIncludeSource($0) }
@@ -929,46 +929,38 @@ struct CashflowStackedChartView: View {
// MARK: - Allocation Evolution Chart // MARK: - Allocation Evolution Chart
struct AllocationEvolutionDataPoint: Identifiable {
let id: String
let date: Date
let category: String
let percentage: Double
let color: String
}
struct AllocationEvolutionChart: View { struct AllocationEvolutionChart: View {
let data: [(date: Date, category: String, percentage: Double, color: String)] let data: [(date: Date, category: String, percentage: Double, color: String)]
private var identifiableData: [AllocationEvolutionDataPoint] {
data.enumerated().map { index, item in
AllocationEvolutionDataPoint(
id: "\(index)-\(item.category)",
date: item.date,
category: item.category,
percentage: item.percentage,
color: item.color
)
}
}
var body: some View { var body: some View {
VStack(alignment: .leading, spacing: 12) { VStack(alignment: .leading, spacing: 12) {
Text("Allocation Over Time") Text("Allocation Over Time")
.font(.headline) .font(.headline)
if data.isEmpty { if data.isEmpty {
Text("Not enough data to show allocation evolution.") emptyView
.foregroundColor(.secondary)
.frame(height: 260)
} else { } else {
Chart { chartView
ForEach(data, id: \.date.description + \.category) { item in
AreaMark(
x: .value("Date", item.date),
y: .value("Percentage", item.percentage)
)
.foregroundStyle(by: .value("Category", item.category))
}
}
.chartForegroundStyleScale(domain: categoryNames, range: categoryColors)
.chartXAxis {
AxisMarks(values: .stride(by: .month, count: 2)) { _ in
AxisValueLabel(format: .dateTime.month(.abbreviated).year(.twoDigits))
}
}
.chartYAxis {
AxisMarks(position: .leading) { value in
AxisValueLabel {
if let pct = value.as(Double.self) {
Text(String(format: "%.0f%%", pct))
.font(.caption)
}
}
}
}
.frame(height: 260)
.drawingGroup()
} }
} }
.padding() .padding()
@@ -977,6 +969,40 @@ struct AllocationEvolutionChart: View {
.shadow(color: .black.opacity(0.05), radius: 8, y: 2) .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
} }
private var emptyView: some View {
Text("Not enough data to show allocation evolution.")
.foregroundColor(.secondary)
.frame(height: 260)
}
private var chartView: some View {
Chart(identifiableData) { item in
AreaMark(
x: .value("Date", item.date),
y: .value("Percentage", item.percentage)
)
.foregroundStyle(by: .value("Category", item.category))
}
.chartForegroundStyleScale(domain: categoryNames, range: categoryColors)
.chartXAxis {
AxisMarks(values: .stride(by: .month, count: 2)) { _ in
AxisValueLabel(format: .dateTime.month(.abbreviated).year(.twoDigits))
}
}
.chartYAxis {
AxisMarks(position: .leading) { value in
AxisValueLabel {
if let pct = value.as(Double.self) {
Text(String(format: "%.0f%%", pct))
.font(.caption)
}
}
}
}
.frame(height: 260)
.drawingGroup()
}
private var categoryNames: [String] { private var categoryNames: [String] {
Array(Set(data.map { $0.category })).sorted() Array(Set(data.map { $0.category })).sorted()
} }