food-market/src/food-market.pos/Views/SaleView.axaml
nns 4b08782e82 fix(pos-ui): полировка по реальному окну Windows 11
Правки по замечаниям на windows11-sale.png (VM 1280×800 maximized — высоты
меньше, чем в headless):

1. Адаптив правой панели по высоте (SaleView.axaml.cs, подписка на Bounds):
   уровни normal/compact/tiny — сжимаются отступы, ИТОГО, кнопки; скрывается
   блок «Последний чек»; ClipToBounds, чтобы ничего не уходило под полосу клавиш.
2. Шапка — Grid вместо StackPanel: чипы в отдельной колонке и не обрезаются;
   адаптив по ширине (MainWindow.axaml.cs): <1400 короткие чипы, <1100 без «Магазин…».
   BadgesCompact во VM переключает тексты ShiftBadge/QueueBadge.
3. Иконка «Выплата» (одиночная горизонталь) схлопывалась при Stretch=Uniform →
   Stretch=None; «Внесение» выровнял так же.
4. Hover строки корзины — светлый #F7FBF8 вместо тёмного из темы.
5. Плитки избранного — Grid *,Auto: цена прибита к низу, у всех на одной линии.
6. Полоса горячих клавиш — выравнивание влево (как в макете).
7. --density: рендер экрана продажи в 1280×720/800, 1366×768, 1920×1080 для проверки.

--uitest OK, 82 unit зелёные, smoke OK, скорость не хуже.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 16:51:51 +05:00

202 lines
17 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:foodmarket.Pos.ViewModels"
x:Class="foodmarket.Pos.Views.SaleView"
x:DataType="vm:SaleViewModel">
<Grid ColumnDefinitions="*,440" Background="{DynamicResource PosBg}">
<!-- ЛЕВО -->
<Grid Grid.Column="0" RowDefinitions="Auto,Auto,Auto,*" Margin="24,16,8,16">
<!-- Поиск / скан -->
<Border Grid.Row="0" Height="64" Background="{DynamicResource PosCard}" BorderBrush="{DynamicResource PosBrand}" BorderThickness="2" CornerRadius="14"
BoxShadow="0 0 0 4 #1F16A34A" Margin="0,0,0,16">
<Grid ColumnDefinitions="Auto,*,Auto">
<Path Grid.Column="0" Width="24" Height="24" Margin="20,0,14,0" Stretch="Uniform" Stroke="{DynamicResource PosBrand}" StrokeThickness="2" StrokeLineCap="Round"
Data="M3 5v14M7 5v14M11 5v14M15 5v14M19 5v14"/>
<TextBox Grid.Column="1" BorderThickness="0" FontSize="19" Background="Transparent" VerticalContentAlignment="Center"
Watermark="Отсканируйте товар или начните вводить название" Text="{Binding ScanInput}">
<TextBox.KeyBindings><KeyBinding Gesture="Enter" Command="{Binding ScanCommand}"/></TextBox.KeyBindings>
</TextBox>
<Border Grid.Column="2" Classes="kbd" Margin="0,0,16,0"><TextBlock Text="F2"/></Border>
</Grid>
</Border>
<!-- Заголовок избранного -->
<Grid Grid.Row="1" ColumnDefinitions="*,Auto" Margin="0,0,0,12" IsVisible="{Binding HasFavorites}">
<TextBlock Text="ИЗБРАННОЕ" FontSize="15" FontWeight="Bold" Foreground="{DynamicResource PosTextMuted}" VerticalAlignment="Center"/>
<Button Grid.Column="1" Background="Transparent" BorderThickness="0" Padding="0" Command="{Binding ToggleFavoritesCommand}" HorizontalAlignment="Right">
<Panel>
<TextBlock FontSize="14" FontWeight="SemiBold" Foreground="{DynamicResource PosBrandDark}" Text="Скрыть ▴" IsVisible="{Binding FavoritesOpen}"/>
<TextBlock FontSize="14" FontWeight="SemiBold" Foreground="{DynamicResource PosBrandDark}" Text="Показать ▾" IsVisible="{Binding !FavoritesOpen}"/>
</Panel>
</Button>
</Grid>
<!-- Избранное -->
<ItemsControl Grid.Row="2" ItemsSource="{Binding Favorites}" Margin="0,0,0,16" IsVisible="{Binding FavoritesOpen}">
<ItemsControl.ItemsPanel><ItemsPanelTemplate><UniformGrid Columns="6"/></ItemsPanelTemplate></ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Height="84" Margin="6" Padding="8,10" Background="{DynamicResource PosCard}" BorderBrush="{DynamicResource PosBorder}" BorderThickness="1" CornerRadius="12"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
Command="{Binding $parent[ItemsControl].((vm:SaleViewModel)DataContext).AddFavoriteCommand}" CommandParameter="{Binding}">
<Grid RowDefinitions="*,Auto">
<TextBlock Grid.Row="0" Text="{Binding Name}" FontSize="15" FontWeight="SemiBold" TextAlignment="Center" TextWrapping="Wrap" MaxLines="2" TextTrimming="CharacterEllipsis"
HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{DynamicResource PosText}"/>
<TextBlock Grid.Row="1" Text="{Binding PriceText}" FontSize="15" FontWeight="Bold" TextAlignment="Center" HorizontalAlignment="Center" Margin="0,4,0,0" Foreground="{DynamicResource PosBrandDark}"/>
</Grid>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Корзина -->
<Border Grid.Row="3" Background="{DynamicResource PosCard}" BorderBrush="{DynamicResource PosBorder}" BorderThickness="1" CornerRadius="14">
<Grid RowDefinitions="Auto,*">
<Border Grid.Row="0" Height="48" BorderBrush="{DynamicResource PosBorder}" BorderThickness="0,0,0,1">
<Grid ColumnDefinitions="*,200,160,56" Margin="20,0">
<TextBlock Text="Товар" Foreground="{DynamicResource PosTextMuted}" FontSize="14" FontWeight="SemiBold" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="Количество" Foreground="{DynamicResource PosTextMuted}" FontSize="14" FontWeight="SemiBold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="Сумма" Foreground="{DynamicResource PosTextMuted}" FontSize="14" FontWeight="SemiBold" HorizontalAlignment="Right" VerticalAlignment="Center"/>
</Grid>
</Border>
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="10" IsVisible="{Binding IsCartEmpty}">
<Border Background="{DynamicResource PosSubtle}" CornerRadius="999" Width="72" Height="72">
<Path Width="34" Height="34" Stretch="Uniform" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="1.6" StrokeLineCap="Round" StrokeJoin="Round"
Data="M6 6h15l-1.5 9h-12zM6 6l-2 -3M9 20a1 1 0 100 .01M18 20a1 1 0 100 .01"/>
</Border>
<TextBlock Text="Отсканируйте первый товар" Foreground="{DynamicResource PosTextMuted}" FontSize="16"/>
</StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding Lines}" SelectedItem="{Binding SelectedLine}"
Background="Transparent" BorderThickness="0" Padding="0" IsVisible="{Binding !IsCartEmpty}">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="0"/><Setter Property="Margin" Value="0"/><Setter Property="CornerRadius" Value="0"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ListBoxItem:selected /template/ ContentPresenter"><Setter Property="Background" Value="Transparent"/></Style>
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter"><Setter Property="Background" Value="Transparent"/></Style>
<Style Selector="Border.row"><Setter Property="Background" Value="Transparent"/></Style>
<Style Selector="Rectangle.accent"><Setter Property="IsVisible" Value="False"/></Style>
<!-- Светлая подсветка строки (как в макете #F7FBF8), а не тёмная из темы -->
<Style Selector="ListBoxItem:pointerover Border.row"><Setter Property="Background" Value="{DynamicResource PosSelRow}"/></Style>
<Style Selector="ListBoxItem:selected Border.row"><Setter Property="Background" Value="{DynamicResource PosSelRow}"/></Style>
<Style Selector="ListBoxItem:selected Rectangle.accent"><Setter Property="IsVisible" Value="True"/></Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:SaleLineVm">
<Border Classes="row" Height="76" BorderBrush="{DynamicResource PosBorder}" BorderThickness="0,0,0,1">
<Grid ColumnDefinitions="4,*,200,160,56">
<Rectangle Grid.Column="0" Classes="accent" Fill="{DynamicResource PosBrand}"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="16,0,0,0">
<TextBlock Text="{Binding Name}" Foreground="{DynamicResource PosText}" FontSize="18" FontWeight="SemiBold" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="{Binding DiscountText}" Foreground="{DynamicResource PosBrandDark}" FontSize="14" FontWeight="Medium" Margin="0,4,0,0" IsVisible="{Binding HasDiscount}"/>
<TextBlock Text="{Binding UnitPriceText}" Foreground="{DynamicResource PosTextMuted}" FontSize="14" Margin="0,4,0,0" IsVisible="{Binding !HasDiscount}"/>
</StackPanel>
<Border Grid.Column="2" Height="44" Margin="16,0" BorderBrush="{DynamicResource PosBorder}" BorderThickness="1" CornerRadius="10" ClipToBounds="True">
<Grid ColumnDefinitions="44,*,44">
<Button Classes="stepbtn" Content="−" Command="{Binding $parent[ItemsControl].((vm:SaleViewModel)DataContext).DecLineCommand}" CommandParameter="{Binding}"/>
<TextBlock Grid.Column="1" Text="{Binding QtyText}" Foreground="{DynamicResource PosText}" FontSize="17" FontWeight="SemiBold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Grid.Column="2" Classes="stepbtn" FontSize="20" Content="+" Command="{Binding $parent[ItemsControl].((vm:SaleViewModel)DataContext).IncLineCommand}" CommandParameter="{Binding}"/>
</Grid>
</Border>
<TextBlock Grid.Column="3" Text="{Binding LineTotal, StringFormat='{}{0:N0} ₸'}" Foreground="{DynamicResource PosText}" FontSize="20" FontWeight="Bold" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<Button Grid.Column="4" Width="44" Height="44" Background="Transparent" BorderThickness="0" HorizontalAlignment="Right" VerticalAlignment="Center"
Command="{Binding $parent[ItemsControl].((vm:SaleViewModel)DataContext).RemoveLineCommand}" CommandParameter="{Binding}" ToolTip.Tip="Удалить">
<Path Width="20" Height="20" Stretch="Uniform" Stroke="#9AA7A1" StrokeThickness="2" StrokeLineCap="Round" StrokeJoin="Round"
Data="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
</Grid>
<!-- ПРАВО -->
<Border Grid.Column="1" Background="{DynamicResource PosCard}" BorderBrush="{DynamicResource PosBorder}" BorderThickness="1" CornerRadius="14" Margin="8,16,24,16" ClipToBounds="True">
<Grid x:Name="RightInner" RowDefinitions="Auto,*,Auto" Margin="24">
<StackPanel x:Name="SummaryStack" Grid.Row="0" Spacing="16">
<Grid ColumnDefinitions="*,Auto"><TextBlock Text="Позиций" Foreground="{DynamicResource PosTextMuted}" FontSize="17"/><TextBlock Grid.Column="1" Text="{Binding ItemCount}" Foreground="{DynamicResource PosText}" FontSize="17" FontWeight="SemiBold"/></Grid>
<Grid ColumnDefinitions="*,Auto"><TextBlock Text="Подытог" Foreground="{DynamicResource PosTextMuted}" FontSize="17"/><TextBlock Grid.Column="1" Text="{Binding Subtotal, StringFormat='{}{0:N0} ₸'}" Foreground="{DynamicResource PosText}" FontSize="17" FontWeight="SemiBold"/></Grid>
<Grid ColumnDefinitions="*,Auto" IsVisible="{Binding HasAnyDiscount}"><TextBlock Text="Скидка" Foreground="{DynamicResource PosTextMuted}" FontSize="17"/><TextBlock Grid.Column="1" Text="{Binding Discount, StringFormat='−{0:N0} ₸'}" Foreground="{DynamicResource PosBrandDark}" FontSize="17" FontWeight="SemiBold"/></Grid>
<Border x:Name="ItogoBorder" Background="{DynamicResource PosBrandSoft}" CornerRadius="12" Padding="22,20">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Text="ИТОГО" Foreground="{DynamicResource PosBrandDark}" FontSize="18" FontWeight="Bold" VerticalAlignment="Bottom"/>
<TextBlock x:Name="ItogoValue" Grid.Column="1" Text="{Binding Total, StringFormat='{}{0:N0} ₸'}" Foreground="{DynamicResource PosBrandDark}" FontSize="52" FontWeight="ExtraBold"/>
</Grid>
</Border>
<Border x:Name="LastCheckBlock" BorderBrush="{DynamicResource PosBorder}" BorderThickness="0,1,0,0" Padding="0,16,0,0">
<StackPanel Spacing="10">
<Grid ColumnDefinitions="*,Auto"><TextBlock Foreground="{DynamicResource PosTextMuted}" FontSize="14"><Run Text="Последний чек "/><Run Text="{Binding LastReceiptNumber}"/></TextBlock><TextBlock Grid.Column="1" Text="{Binding LastReceiptInfo}" Foreground="{DynamicResource PosText}" FontSize="14" FontWeight="SemiBold"/></Grid>
<Grid ColumnDefinitions="*,Auto"><TextBlock Text="Чеков за смену" Foreground="{DynamicResource PosTextMuted}" FontSize="14"/><TextBlock Grid.Column="1" Text="{Binding ReceiptsInShift}" Foreground="{DynamicResource PosText}" FontSize="14" FontWeight="SemiBold"/></Grid>
</StackPanel>
</Border>
</StackPanel>
<StackPanel Grid.Row="2" Spacing="12">
<Button x:Name="PayButton" Classes="pos primary" HorizontalAlignment="Stretch" Height="76" Command="{Binding PayCommand}">
<StackPanel Orientation="Horizontal" Spacing="12" HorizontalAlignment="Center">
<TextBlock Text="Оплатить" FontSize="24" FontWeight="Bold" Foreground="White" VerticalAlignment="Center"/>
<Border Classes="kbd onbrand"><TextBlock Text="F12"/></Border>
</StackPanel>
</Button>
<Grid x:Name="ActionsGrid" ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto,Auto">
<Button Grid.Row="0" Grid.Column="0" Classes="pos ghost" Height="52" Margin="0,0,5,10">
<StackPanel Orientation="Horizontal" Spacing="10">
<Path Width="18" Height="18" Stretch="Uniform" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="2" StrokeLineCap="Round" Data="M19 5L5 19M7 7h.01M17 17h.01"/>
<TextBlock Text="Скидка" VerticalAlignment="Center"/><Border Classes="kbd"><TextBlock Text="F4"/></Border>
</StackPanel>
</Button>
<Button Grid.Row="0" Grid.Column="1" Classes="pos ghost" Height="52" Margin="5,0,0,10" Command="{Binding ParkCommand}">
<StackPanel Orientation="Horizontal" Spacing="10">
<Path Width="18" Height="18" Stretch="Uniform" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="2" StrokeJoin="Round" Data="M6 4h12v16l-6-4-6 4z"/>
<TextBlock Text="Отложить" VerticalAlignment="Center"/><Border Classes="kbd"><TextBlock Text="F7"/></Border>
</StackPanel>
</Button>
<Button Grid.Row="1" Grid.Column="0" Classes="pos ghost" Height="52" Margin="0,0,5,10" Command="{Binding ResumeCommand}">
<StackPanel Orientation="Horizontal" Spacing="10">
<Path Width="18" Height="18" Stretch="Uniform" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="2" StrokeLineCap="Round" Data="M4 6h16M4 12h16M4 18h10"/>
<TextBlock Text="Отложенные" VerticalAlignment="Center"/>
<Border CornerRadius="999" MinWidth="22" Height="22" Padding="7,0" Background="{DynamicResource PosWarnSoft}" VerticalAlignment="Center" IsVisible="{Binding HasParked}">
<TextBlock Text="{Binding ParkedCount}" FontSize="13" FontWeight="Bold" Foreground="{DynamicResource PosWarn}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</StackPanel>
</Button>
<Button Grid.Row="1" Grid.Column="1" Classes="pos ghost" Height="52" Margin="5,0,0,10" Command="{Binding GoReturnCommand}">
<StackPanel Orientation="Horizontal" Spacing="10">
<Path Width="18" Height="18" Stretch="Uniform" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="2" StrokeLineCap="Round" StrokeJoin="Round" Data="M9 14L4 9l5-5M4 9h11a5 5 0 010 10h-3"/>
<TextBlock Text="Возврат" VerticalAlignment="Center"/><Border Classes="kbd"><TextBlock Text="F9"/></Border>
</StackPanel>
</Button>
<Button Grid.Row="2" Grid.Column="0" Classes="pos ghost" Height="52" Margin="0,0,5,10" Command="{Binding GoShiftCommand}">
<StackPanel Orientation="Horizontal" Spacing="10">
<Path Width="18" Height="18" Stretch="None" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="2" StrokeLineCap="Round" Data="M9 3v12M3 9h12"/>
<TextBlock Text="Внесение" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button Grid.Row="2" Grid.Column="1" Classes="pos ghost" Height="52" Margin="5,0,0,10" Command="{Binding GoShiftCommand}">
<StackPanel Orientation="Horizontal" Spacing="10">
<!-- Минус: Stretch=None — одиночная горизонталь при Uniform схлопывается в точку -->
<Path Width="18" Height="18" Stretch="None" Stroke="{DynamicResource PosTextMuted}" StrokeThickness="2" StrokeLineCap="Round" Data="M3 9h12"/>
<TextBlock Text="Выплата" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Classes="pos danger" Height="52" Command="{Binding ClearCommand}">
<StackPanel Orientation="Horizontal" Spacing="10">
<Path Width="18" Height="18" Stretch="Uniform" Stroke="{DynamicResource PosDanger}" StrokeThickness="2" StrokeLineCap="Round" Data="M6 6l12 12M18 6L6 18"/>
<TextBlock Text="Очистить чек" VerticalAlignment="Center"/><Border Classes="kbd"><TextBlock Text="Esc"/></Border>
</StackPanel>
</Button>
</Grid>
</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>