Files
Clario/Clario/Views/BudgetView.axaml
2026-03-26 20:42:15 +03:00

605 lines
42 KiB
XML

<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Clario.ViewModels"
xmlns:lvc="using:LiveChartsCore.SkiaSharpView.Avalonia"
xmlns:views="clr-namespace:Clario.Views"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:skiaSharpView="clr-namespace:LiveChartsCore.SkiaSharpView;assembly=LiveChartsCore.SkiaSharpView"
xmlns:model="clr-namespace:Clario.Models"
x:DataType="vm:BudgetViewModel"
mc:Ignorable="d" d:DesignWidth="1180" d:DesignHeight="800"
x:Class="Clario.Views.BudgetView">
<Design.DataContext>
<vm:BudgetViewModel />
</Design.DataContext>
<!-- ═══════════════════════════════════════════════════
ROOT
═══════════════════════════════════════════════════ -->
<Grid RowDefinitions="Auto,*"
Margin="32,28,32,0">
<!-- ══════════════════════════════════════════
TOP BAR
══════════════════════════════════════════ -->
<Grid Grid.Row="0"
ColumnDefinitions="*,Auto"
Margin="0,0,0,24">
<StackPanel Grid.Column="0">
<!-- REPLACE: bind to CurrentPeriodLabel e.g. "March 2026" -->
<TextBlock Text="{Binding CurrentPeriodFormatted}"
FontSize="12"
Foreground="{DynamicResource TextMuted}" />
<TextBlock Text="Budget"
FontSize="26"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}"
Margin="0,2,0,0" />
</StackPanel>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
Spacing="10"
VerticalAlignment="Center">
<!-- Period navigator -->
<Border Background="{DynamicResource BgSurface}"
BorderBrush="{DynamicResource BorderSubtle}"
BorderThickness="1"
CornerRadius="10">
<StackPanel Orientation="Horizontal">
<!-- REPLACE: Command="{Binding PreviousPeriodCommand}" -->
<Button Background="Transparent"
Classes="nav textless"
BorderThickness="0"
Padding="10,8"
Cursor="Hand"
Command="{Binding PreviousPeriodCommand}">
<Svg Path="../Assets/Icons/chevron-left.svg"
Width="14" Height="14"
Css="{DynamicResource SvgMuted}" />
</Button>
<!-- REPLACE: bind to CurrentPeriodLabel -->
<TextBlock Text="{Binding CurrentPeriodFormatted}"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}"
VerticalAlignment="Center"
Margin="4,0" />
<!-- REPLACE: Command="{Binding NextPeriodCommand}" -->
<Button Background="Transparent"
Classes="nav textless"
BorderThickness="0"
Padding="10,8"
Cursor="Hand"
Command="{Binding NextPeriodCommand}">
<Svg Path="../Assets/Icons/chevron-right.svg"
Width="14" Height="14"
Css="{DynamicResource SvgMuted}" />
</Button>
</StackPanel>
</Border>
<!-- Add budget button -->
<!-- REPLACE: Command="{Binding AddBudgetCommand}" -->
<Button Classes="accented"
Padding="16,9">
<Button.Flyout>
<Flyout Placement="LeftEdgeAlignedTop"
FlyoutPresenterTheme="{StaticResource TransparentFlyoutPresenter}">
<views:BudgetFormView />
</Flyout>
</Button.Flyout>
<StackPanel Orientation="Horizontal" Spacing="8">
<Svg Path="../Assets/Icons/plus.svg"
Width="14" Height="14"
Css="path, circle, rect, ellipse, line, polyline, polygon, text, use { stroke: #0D0F14; }" />
<TextBlock Text="Add Budget"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource BgBase}"
VerticalAlignment="Center" />
</StackPanel>
</Button>
</StackPanel>
</Grid>
<!-- ══════════════════════════════════════════
MAIN CONTENT
Left * — budget categories
Right 320 — monthly overview panel
══════════════════════════════════════════ -->
<Grid Grid.Row="1" ColumnDefinitions="*,320">
<!-- ─────────────────────────────────────
LEFT — Budget Categories
───────────────────────────────────── -->
<ScrollViewer Grid.Column="0"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Margin="0,0,12,0" Padding="0 0 8 0">
<ItemsControl ItemsSource="{Binding VisibleBudgets}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="12" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="model:Budget">
<Panel>
<TextBlock IsVisible="{Binding GroupHeader}"
Text="{Binding Category.Name}"
Classes="label"
Margin="0,0,0,4" />
<Border IsVisible="{Binding !GroupHeader}"
Classes.budget-card="{Binding IsOnTrack}"
Classes.budget-card-warning="{Binding IsWarning}"
Classes.budget-card-over="{Binding IsOverBudget}"
Background="{DynamicResource BgSurface}"
CornerRadius="16"
Padding="20"
Cursor="Hand">
<StackPanel Spacing="14">
<!-- Header row -->
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
<Border Grid.Column="0"
CornerRadius="10"
Width="40" Height="40"
Margin="0,0,14,0">
<Border.Background>
<SolidColorBrush
Color="{Binding Category.Color,Converter={StaticResource HexToColorConverter}, ConverterParameter=color}"
Opacity="0.15" />
</Border.Background>
<Svg Path="{Binding Category.Icon, Converter={StaticResource SvgPathFromName}}"
Width="18" Height="18"
Css="{Binding Category.Color,Converter={StaticResource HexToColorConverter}, ConverterParameter=css}" />
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Center" Spacing="2">
<!-- REPLACE: bind to Budget.CategoryName -->
<TextBlock Text="{Binding Category.Name}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<!-- REPLACE: bind to Budget.TransactionCount -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding TransactionsCount}"
FontSize="11"
Foreground="{DynamicResource TextMuted}" />
<TextBlock Text=" transactions"
FontSize="11"
Foreground="{DynamicResource TextMuted}" />
</StackPanel>
</StackPanel>
<!-- Spent / Limit -->
<StackPanel Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Spacing="2"
Margin="0,0,12,0">
<!-- REPLACE: bind to Budget.SpentFormatted -->
<TextBlock Text="{Binding SpentFormatted}"
FontSize="14"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}"
HorizontalAlignment="Right" />
<!-- REPLACE: bind to Budget.LimitFormatted -->
<TextBlock Text="{Binding AmountFormatted}"
FontSize="11"
Foreground="{DynamicResource TextMuted}"
HorizontalAlignment="Right" />
</StackPanel>
<!-- Edit button -->
<!-- REPLACE: Command="{Binding EditBudgetCommand}" CommandParameter="{Binding}" -->
<Button Grid.Column="3"
Background="Transparent"
BorderThickness="0"
Padding="4"
VerticalAlignment="Center"
Cursor="Hand">
<Button.Flyout>
<Flyout Placement="BottomEdgeAlignedRight"
FlyoutPresenterTheme="{StaticResource TransparentFlyoutPresenter}">
<views:BudgetCardMenuView />
</Flyout>
</Button.Flyout>
<Svg Path="../Assets/Icons/ellipsis.svg"
Width="15" Height="15"
Css="{DynamicResource SvgMuted}" />
</Button>
</Grid>
<!-- Progress bar + remaining -->
<StackPanel Spacing="6">
<!-- REPLACE: Value="{Binding Budget.PercentageUsed}" -->
<ProgressBar Classes.green="{Binding IsOnTrack}"
Classes.yellow="{Binding IsWarning}"
Classes.red="{Binding IsOverBudget}"
Value="{Binding Spent}"
Minimum="0"
Maximum="{Binding LimitAmount}"
Height="6" />
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="6">
<Border Classes.badge-green="{Binding IsOnTrack}"
Classes.badge-yellow="{Binding IsWarning}"
Classes.badge-red="{Binding IsOverBudget}"
CornerRadius="20"
Padding="6,2">
<StackPanel Orientation="Horizontal" Spacing="4">
<Svg Path="../Assets/Icons/triangle-alert.svg" Css="{DynamicResource SvgYellow}"
IsVisible="{Binding IsWarning}" Height="13" VerticalAlignment="Center" />
<Svg Path="../Assets/Icons/circle-alert.svg" Css="{DynamicResource SvgRed}"
IsVisible="{Binding IsOverBudget}" Height="13" VerticalAlignment="Center" />
<TextBlock Text="{Binding PercentageFormatted}"
FontSize="11" VerticalAlignment="Center" />
</StackPanel>
</Border>
</StackPanel>
<!-- REPLACE: bind to Budget.RemainingFormatted -->
<TextBlock Grid.Column="1"
Text="{Binding RemainingFormatted}"
FontSize="11"
Foreground="{DynamicResource TextMuted}"
VerticalAlignment="Center" />
</Grid>
</StackPanel>
</StackPanel>
</Border>
</Panel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- ─────────────────────────────────────
RIGHT — Overview Panel
───────────────────────────────────── -->
<ScrollViewer Grid.Column="1"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled" Margin="0,0,0,0" Padding="0 0 8 0">
<StackPanel Spacing="14" Margin="0 0 0 28">
<!-- ── Period Overview ───────────────── -->
<Border Background="{DynamicResource BgSurface}"
BorderBrush="{DynamicResource BorderSubtle}"
BorderThickness="1"
CornerRadius="16"
Padding="22">
<StackPanel Spacing="18">
<TextBlock Text="Period Overview"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<!-- Total budgeted vs spent -->
<StackPanel Spacing="8">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Total Budgeted" FontSize="12" Foreground="{DynamicResource TextMuted}" />
<!-- REPLACE: bind to TotalBudgetedFormatted -->
<TextBlock Grid.Column="1" Text="{Binding TotalBudgeted, StringFormat='$0'}" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Total Spent" FontSize="12" Foreground="{DynamicResource TextMuted}" />
<!-- REPLACE: bind to TotalSpentFormatted -->
<TextBlock Grid.Column="1" Text="{Binding TotalSpent, StringFormat='$0'}" FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
</Grid>
<!-- Overall progress bar -->
<StackPanel Spacing="5" Margin="0,4,0,0">
<!-- REPLACE: Value="{Binding OverallPercentageUsed}" -->
<ProgressBar Classes="green" Value="{Binding TotalSpent}" Minimum="0" Maximum="{Binding TotalBudgeted}" Height="8" />
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="{Binding SpentPercentageFormatted}" FontSize="11"
Foreground="{DynamicResource TextMuted}" />
<!-- REPLACE: bind to TotalRemainingFormatted -->
<TextBlock Grid.Column="1" Text="{Binding TotalLeftFormatted}" FontSize="11" Foreground="{DynamicResource AccentGreen}" />
</Grid>
</StackPanel>
</StackPanel>
<Separator />
<!-- Status summary rows -->
<StackPanel Spacing="10">
<!-- On track count -->
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0"
Background="{DynamicResource IconBgGreen}"
CornerRadius="6"
Width="28" Height="28"
Margin="0,0,10,0">
<Svg Path="../Assets/Icons/check.svg" Width="13" Height="13" Css="{DynamicResource SvgGreen}" />
</Border>
<TextBlock Grid.Column="1" Text="On track" FontSize="13" Foreground="{DynamicResource TextSecondary}"
VerticalAlignment="Center" />
<!-- REPLACE: bind to OnTrackCount -->
<TextBlock Grid.Column="2" Text="{Binding OnTrackCountFormatted}" FontSize="12" Foreground="{DynamicResource AccentGreen}"
VerticalAlignment="Center" />
</Grid>
<!-- Warning count -->
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0"
Background="{DynamicResource BadgeBgYellow}"
CornerRadius="6"
Width="28" Height="28"
Margin="0,0,10,0">
<Svg Path="../Assets/Icons/triangle-alert.svg" Width="13" Height="13"
Css="path, circle, rect, ellipse, line, polyline, polygon, text, use { stroke: #F5C842; }" />
</Border>
<TextBlock Grid.Column="1" Text="Approaching limit" FontSize="13" Foreground="{DynamicResource TextSecondary}"
VerticalAlignment="Center" />
<!-- REPLACE: bind to WarningCount -->
<TextBlock Grid.Column="2" Text="{Binding ApproachingCountFormatted}" FontSize="12"
Foreground="{DynamicResource AccentYellow}"
VerticalAlignment="Center" />
</Grid>
<!-- Over budget count -->
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0"
Background="{DynamicResource BadgeBgRed}"
CornerRadius="6"
Width="28" Height="28"
Margin="0,0,10,0">
<Svg Path="../Assets/Icons/circle-alert.svg" Width="13" Height="13"
Css="path, circle, rect, ellipse, line, polyline, polygon, text, use { stroke: #FF5E5E; }" />
</Border>
<TextBlock Grid.Column="1" Text="Over budget" FontSize="13" Foreground="{DynamicResource TextSecondary}"
VerticalAlignment="Center" />
<!-- REPLACE: bind to OverBudgetCount -->
<TextBlock Grid.Column="2" Text="{Binding OverBudgetCountFormatted}" FontSize="12" Foreground="{DynamicResource AccentRed}"
VerticalAlignment="Center" />
</Grid>
</StackPanel>
</StackPanel>
</Border>
<!-- ── Days remaining in period ───────── -->
<Border Background="{DynamicResource BgSurface}"
BorderBrush="{DynamicResource BorderSubtle}"
BorderThickness="1"
CornerRadius="16"
Padding="22">
<StackPanel Spacing="14">
<Grid ColumnDefinitions="Auto,*">
<Border Grid.Column="0"
Background="{DynamicResource IconBgBlue}"
CornerRadius="10"
Width="40" Height="40"
Margin="0,0,14,0">
<Svg Path="../Assets/Icons/calendar-days.svg" Width="18" Height="18" Css="{DynamicResource SvgBlue}" />
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Center" Spacing="2">
<TextBlock Text="Period Progress" FontSize="13" FontWeight="SemiBold" Foreground="{DynamicResource TextPrimary}" />
<!-- REPLACE: bind to PeriodProgressLabel e.g. "22 of 31 days" -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PeriodDaysPassed}" FontSize="11" Foreground="{DynamicResource TextMuted}" />
<TextBlock Text=" of " FontSize="11" Foreground="{DynamicResource TextMuted}" />
<TextBlock Text="{Binding PeriodLength}" FontSize="11" Foreground="{DynamicResource TextMuted}" />
<TextBlock Text=" days elapsed" FontSize="11" Foreground="{DynamicResource TextMuted}" />
</StackPanel>
</StackPanel>
</Grid>
<!-- REPLACE: Value="{Binding PeriodDayPercentage}" -->
<ProgressBar Classes="blue" Value="{Binding PeriodDaysPassed}" Minimum="0" Maximum="{Binding PeriodLength}" Height="6" />
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Days remaining" FontSize="12" Foreground="{DynamicResource TextMuted}" />
<!-- REPLACE: bind to DaysRemainingLabel -->
<TextBlock Grid.Column="1" Text="{Binding PeriodDaysLeftFormatted}" FontSize="12" FontWeight="SemiBold"
Foreground="{DynamicResource AccentBlue}" />
</Grid>
<Separator />
<!-- Daily remaining spend -->
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="2">
<TextBlock Text="Daily budget left" FontSize="12" Foreground="{DynamicResource TextMuted}" />
<TextBlock Text="Based on remaining budget ÷ days" FontSize="10" Foreground="{DynamicResource TextDisabled}" />
</StackPanel>
<!-- REPLACE: bind to DailyRemainingFormatted -->
<TextBlock Grid.Column="1"
Text="{Binding DailyBudgetLeftFormatted}"
FontSize="16"
FontWeight="Bold"
Foreground="{DynamicResource TextPrimary}"
VerticalAlignment="Center" />
</Grid>
</StackPanel>
</Border>
<!-- ── Spending Breakdown ─────────────── -->
<Border Background="{DynamicResource BgSurface}"
BorderBrush="{DynamicResource BorderSubtle}"
BorderThickness="1"
CornerRadius="16"
Padding="22">
<StackPanel Spacing="16">
<TextBlock Text="Spending Breakdown"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
<Border Height="150" ClipToBounds="True">
<lvc:PieChart Series="{Binding SpendingBreakdownChartSeries}" Height="300" LegendPosition="Hidden" InitialRotation="-180"
MaxAngle="180" FlowDirection="LeftToRight" VerticalAlignment="Top" Background="{DynamicResource BgSurface}">
</lvc:PieChart>
</Border>
<ItemsControl ItemsSource="{Binding SpendingBreakdownLegends}" Margin="0 16 0 0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel ItemSpacing="0" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="model:Budget">
<StackPanel Orientation="Horizontal" Spacing="4" IsVisible="{Binding !GroupHeader }" Margin="0 0 8 0">
<Border Height="10" Width="10" CornerRadius="5"
Background="{Binding Category.Color,Converter={StaticResource HexToColorConverter},ConverterParameter='brush'}" />
<TextBlock Text="{Binding Category.Name}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- REPLACE: ItemsSource="{Binding SpendingBreakdown}" with DataTemplate -->
<!-- Row: Food -->
<!-- <Grid ColumnDefinitions="Auto,*,Auto"> -->
<!-- <Border Grid.Column="0" Background="{DynamicResource IconBgGreen}" CornerRadius="6" Width="10" Height="10" Margin="0,0,10,0" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <TextBlock Grid.Column="1" Text="Food &amp; Dining" FontSize="12" Foreground="{DynamicResource TextSecondary}" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <StackPanel Grid.Column="2" HorizontalAlignment="Right" Spacing="1"> -->
<!-- <TextBlock Text="$340" FontSize="12" FontWeight="SemiBold" Foreground="{DynamicResource TextPrimary}" -->
<!-- HorizontalAlignment="Right" /> -->
<!-- <TextBlock Text="21%" FontSize="10" Foreground="{DynamicResource TextMuted}" HorizontalAlignment="Right" /> -->
<!-- </StackPanel> -->
<!-- </Grid> -->
<!-- Row: Housing -->
<!-- <Grid ColumnDefinitions="Auto,*,Auto"> -->
<!-- <Border Grid.Column="0" Background="{DynamicResource AccentOrange}" CornerRadius="6" Width="10" Height="10" Margin="0,0,10,0" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <TextBlock Grid.Column="1" Text="Housing" FontSize="12" Foreground="{DynamicResource TextSecondary}" VerticalAlignment="Center" /> -->
<!-- <StackPanel Grid.Column="2" HorizontalAlignment="Right" Spacing="1"> -->
<!-- <TextBlock Text="$540" FontSize="12" FontWeight="SemiBold" Foreground="{DynamicResource TextPrimary}" -->
<!-- HorizontalAlignment="Right" /> -->
<!-- <TextBlock Text="34%" FontSize="10" Foreground="{DynamicResource TextMuted}" HorizontalAlignment="Right" /> -->
<!-- </StackPanel> -->
<!-- </Grid> -->
<!-- Row: Transport -->
<!-- <Grid ColumnDefinitions="Auto,*,Auto"> -->
<!-- <Border Grid.Column="0" Background="{DynamicResource AccentBlue}" CornerRadius="6" Width="10" Height="10" Margin="0,0,10,0" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <TextBlock Grid.Column="1" Text="Transport" FontSize="12" Foreground="{DynamicResource TextSecondary}" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <StackPanel Grid.Column="2" HorizontalAlignment="Right" Spacing="1"> -->
<!-- <TextBlock Text="$110" FontSize="12" FontWeight="SemiBold" Foreground="{DynamicResource TextPrimary}" -->
<!-- HorizontalAlignment="Right" /> -->
<!-- <TextBlock Text="7%" FontSize="10" Foreground="{DynamicResource TextMuted}" HorizontalAlignment="Right" /> -->
<!-- </StackPanel> -->
<!-- </Grid> -->
<!-- Row: Shopping (over) -->
<!-- <Grid ColumnDefinitions="Auto,*,Auto"> -->
<!-- <Border Grid.Column="0" Background="{DynamicResource AccentRed}" CornerRadius="6" Width="10" Height="10" Margin="0,0,10,0" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <TextBlock Grid.Column="1" Text="Shopping" FontSize="12" Foreground="{DynamicResource TextSecondary}" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <StackPanel Grid.Column="2" HorizontalAlignment="Right" Spacing="1"> -->
<!-- <TextBlock Text="$380" FontSize="12" FontWeight="SemiBold" Foreground="{DynamicResource AccentRed}" -->
<!-- HorizontalAlignment="Right" /> -->
<!-- <TextBlock Text="24%" FontSize="10" Foreground="{DynamicResource TextMuted}" HorizontalAlignment="Right" /> -->
<!-- </StackPanel> -->
<!-- </Grid> -->
<!-- Row: Leisure -->
<!-- <Grid ColumnDefinitions="Auto,*,Auto"> -->
<!-- <Border Grid.Column="0" Background="{DynamicResource AccentPurple}" CornerRadius="6" Width="10" Height="10" Margin="0,0,10,0" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <TextBlock Grid.Column="1" Text="Entertainment" FontSize="12" Foreground="{DynamicResource TextSecondary}" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <StackPanel Grid.Column="2" HorizontalAlignment="Right" Spacing="1"> -->
<!-- <TextBlock Text="$170" FontSize="12" FontWeight="SemiBold" Foreground="{DynamicResource TextPrimary}" -->
<!-- HorizontalAlignment="Right" /> -->
<!-- <TextBlock Text="11%" FontSize="10" Foreground="{DynamicResource TextMuted}" HorizontalAlignment="Right" /> -->
<!-- </StackPanel> -->
<!-- </Grid> -->
<!-- Row: Health -->
<!-- <Grid ColumnDefinitions="Auto,*,Auto"> -->
<!-- <Border Grid.Column="0" Background="{DynamicResource AccentPink}" CornerRadius="6" Width="10" Height="10" Margin="0,0,10,0" -->
<!-- VerticalAlignment="Center" /> -->
<!-- <TextBlock Grid.Column="1" Text="Health" FontSize="12" Foreground="{DynamicResource TextSecondary}" VerticalAlignment="Center" /> -->
<!-- <StackPanel Grid.Column="2" HorizontalAlignment="Right" Spacing="1"> -->
<!-- <TextBlock Text="$69" FontSize="12" FontWeight="SemiBold" Foreground="{DynamicResource TextPrimary}" -->
<!-- HorizontalAlignment="Right" /> -->
<!-- <TextBlock Text="4%" FontSize="10" Foreground="{DynamicResource TextMuted}" HorizontalAlignment="Right" /> -->
<!-- </StackPanel> -->
<!-- </Grid> -->
</StackPanel>
</Border>
<!-- ── Savings Goal ───────────────────── -->
<Border Background="{DynamicResource BgSurface}"
BorderBrush="{DynamicResource BorderSubtle}"
BorderThickness="1"
CornerRadius="16"
Padding="22">
<StackPanel Spacing="14">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0"
Text="Savings Goal"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}"
VerticalAlignment="Center" />
<!-- REPLACE: Command="{Binding EditSavingsGoalCommand}" -->
<Button Grid.Column="1"
Background="Transparent"
BorderThickness="0"
Padding="4"
Cursor="Hand">
<Svg Path="../Assets/Icons/pencil.svg" Width="14" Height="14" Css="{DynamicResource SvgMuted}" />
</Button>
</Grid>
<!-- Goal amount vs projected -->
<StackPanel Spacing="6">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Monthly goal" FontSize="12" Foreground="{DynamicResource TextMuted}" />
<!-- REPLACE: bind to SavingsGoalFormatted -->
<TextBlock Grid.Column="1" Text="{Binding Profile.SavingsGoal, StringFormat='$0'}" FontSize="12" FontWeight="SemiBold"
Foreground="{DynamicResource TextPrimary}" />
</Grid>
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Projected savings" FontSize="12" Foreground="{DynamicResource TextMuted}" />
<!-- REPLACE: bind to ProjectedSavingsFormatted -->
<TextBlock Grid.Column="1" Text="{Binding TotalLeftFormatted}" FontSize="12" FontWeight="SemiBold"
Foreground="{DynamicResource AccentYellow}" />
</Grid>
</StackPanel>
<!-- REPLACE: Value="{Binding SavingsGoalPercentage}" -->
<ProgressBar Classes="yellow" Value="{Binding TotalLeft}" Minimum="0" Maximum="{Binding Profile.SavingsGoal}" Height="6" />
<Border Background="{DynamicResource BadgeBgYellow}"
CornerRadius="10"
Padding="12,8">
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="8">
<Svg Grid.Column="0" Path="../Assets/Icons/info.svg" Width="14" Height="14"
Css="path, circle, rect, ellipse, line, polyline, polygon, text, use { stroke: #F5C842; }" />
<TextBlock Grid.Column="1" Text="{Binding SavingsHint}"
FontSize="12"
Foreground="{DynamicResource AccentYellow}"
TextWrapping="Wrap"
VerticalAlignment="Center" />
</Grid>
</Border>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</Grid>
</Grid>
</UserControl>