mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-03 00:17:47 +00:00
feat(bar-app): inline spend chart bars/line toggle in the Spend header
Move the bars/line choice out of Settings and into the Spend section header's blank space as a small inline toggle, so the user flips the chart style right where the chart is. Persistence unchanged.
This commit is contained in:
@@ -22,6 +22,10 @@ struct BarAnalyticsView: View {
|
|||||||
/// Controls whether the spend sparkline renders as bars or a line graph.
|
/// Controls whether the spend sparkline renders as bars or a line graph.
|
||||||
/// Passed in by BarMenuView so it reflects the user's persisted choice live.
|
/// Passed in by BarMenuView so it reflects the user's persisted choice live.
|
||||||
var spendChartStyle: SpendChartStyle = .bars
|
var spendChartStyle: SpendChartStyle = .bars
|
||||||
|
/// Inline flip for the spend chart style, surfaced as a small toggle in the
|
||||||
|
/// Spend header (using the otherwise-blank space) so the user switches
|
||||||
|
/// bars/line in place rather than digging into Settings. nil for `.breakdown`.
|
||||||
|
var onToggleSpendStyle: (() -> Void)? = nil
|
||||||
|
|
||||||
private var lastActive: String? {
|
private var lastActive: String? {
|
||||||
BarFormatting.lastActiveLabel(
|
BarFormatting.lastActiveLabel(
|
||||||
@@ -71,7 +75,23 @@ struct BarAnalyticsView: View {
|
|||||||
/// line, and a thin inline 30-day sparkline when there is real spend.
|
/// line, and a thin inline 30-day sparkline when there is real spend.
|
||||||
private var spendStrip: some View {
|
private var spendStrip: some View {
|
||||||
VStack(alignment: .leading, spacing: 5) {
|
VStack(alignment: .leading, spacing: 5) {
|
||||||
SectionLabel("Spend")
|
HStack(spacing: 6) {
|
||||||
|
SectionLabel("Spend")
|
||||||
|
Spacer()
|
||||||
|
// Inline bars/line toggle in the header's blank space — no Settings trip.
|
||||||
|
if let toggle = onToggleSpendStyle, analytics.hasRecentData, !sparklineIsEmpty {
|
||||||
|
Button(action: toggle) {
|
||||||
|
Image(
|
||||||
|
systemName: spendChartStyle == .bars
|
||||||
|
? "chart.line.uptrend.xyaxis" : "chart.bar.fill"
|
||||||
|
)
|
||||||
|
.font(.system(size: 10))
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderless)
|
||||||
|
.foregroundStyle(.tertiary)
|
||||||
|
.help("Spend graph: switch to \(spendChartStyle == .bars ? "line" : "bars")")
|
||||||
|
}
|
||||||
|
}
|
||||||
if analytics.hasRecentData {
|
if analytics.hasRecentData {
|
||||||
Text(spendCaption)
|
Text(spendCaption)
|
||||||
.font(.caption2)
|
.font(.caption2)
|
||||||
|
|||||||
@@ -50,12 +50,17 @@ struct BarMenuView: View {
|
|||||||
accountsSection
|
accountsSection
|
||||||
|
|
||||||
// (3) SPEND — demoted to a thin informational strip below the cockpit.
|
// (3) SPEND — demoted to a thin informational strip below the cockpit.
|
||||||
// spendChartStyle is threaded from the viewModel so a live change in
|
// spendChartStyle is threaded from the viewModel and toggled inline
|
||||||
// Settings immediately updates the chart without a refresh.
|
// from the Spend header, so a change updates the chart immediately.
|
||||||
if let analytics = viewModel.analytics {
|
if let analytics = viewModel.analytics {
|
||||||
Divider()
|
Divider()
|
||||||
BarAnalyticsView(analytics: analytics, section: .spend,
|
BarAnalyticsView(
|
||||||
spendChartStyle: viewModel.spendChartStyle)
|
analytics: analytics, section: .spend,
|
||||||
|
spendChartStyle: viewModel.spendChartStyle,
|
||||||
|
onToggleSpendStyle: {
|
||||||
|
viewModel.spendChartStyle =
|
||||||
|
viewModel.spendChartStyle == .bars ? .line : .bars
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// (4) POOL ACCOUNTS — compact generic rows, subordinate.
|
// (4) POOL ACCOUNTS — compact generic rows, subordinate.
|
||||||
|
|||||||
@@ -62,13 +62,8 @@ struct BarPreferencesView: View {
|
|||||||
Text("Dark").tag(BarAppearance.dark)
|
Text("Dark").tag(BarAppearance.dark)
|
||||||
}
|
}
|
||||||
.pickerStyle(.segmented)
|
.pickerStyle(.segmented)
|
||||||
// Changing this live-updates the spend chart in the open dropdown because
|
// Spend graph bars/line is toggled inline in the dropdown's Spend header,
|
||||||
// viewModel.spendChartStyle is @Published and SpendChartStyleStore persists it.
|
// not here — kept out of Settings so the choice lives where the chart is.
|
||||||
Picker("Spend graph", selection: $viewModel.spendChartStyle) {
|
|
||||||
Text("Bars").tag(SpendChartStyle.bars)
|
|
||||||
Text("Line").tag(SpendChartStyle.line)
|
|
||||||
}
|
|
||||||
.pickerStyle(.segmented)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user