krona-staff/apps/KronaStaffTerminal/MainPage.xaml
Ochenstarik 4d37350757
Some checks are pending
ci / verify (push) Waiting to run
feat(terminal): update attendance terminal to 0.2.4
2026-09-20 23:40:43 +07:00

316 lines
22 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.

<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="KronaStaffTerminal.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:models="using:KronaStaffTerminal.Models"
Loaded="Page_Loaded"
Unloaded="Page_Unloaded"
mc:Ignorable="d">
<Grid Background="{ThemeResource KronaAppBackgroundBrush}">
<Grid x:Name="ProtectedContent"
Visibility="Collapsed"
Padding="24,16,24,24"
RowSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<InfoBar x:Name="StatusBar"
IsOpen="True"
IsClosable="False"
Severity="Informational"
Title="Подключение"
Message="Запуск терминала…"/>
<InfoBar x:Name="UpdateBar"
Grid.Row="1"
Margin="0,0,0,4"
IsOpen="False"
IsClosable="True"
Severity="Informational"
Title="Доступно обновление">
<InfoBar.ActionButton>
<Button Content="Обновить"
Click="InstallUpdate_Click"/>
</InfoBar.ActionButton>
</InfoBar>
<TabView x:Name="MainTabs"
Grid.Row="2"
Background="{ThemeResource KronaWorkspaceBrush}"
IsAddTabButtonVisible="False"
SelectionChanged="MainTabs_SelectionChanged">
<TabViewItem x:Name="TerminalTab" Header="Терминал" IsClosable="False">
<Grid Padding="4,16,4,4" ColumnSpacing="24">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Border Margin="8"
Padding="28"
Background="{ThemeResource KronaSurfaceBrush}"
BorderBrush="{ThemeResource KronaBorderBrush}"
BorderThickness="1"
CornerRadius="{StaticResource KronaRadiusLarge}">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="14">
<Grid Width="220" Height="220">
<Ellipse Fill="{ThemeResource KronaGoldSoftBrush}" />
<Image Margin="18"
Source="Assets/TrushenkoLogo.png"
Stretch="Uniform"
AutomationProperties.Name="Логотип Трушенко" />
<Border Width="54"
Height="54"
Margin="0,0,4,4"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Background="{ThemeResource KronaPrimaryBrush}"
CornerRadius="27">
<FontIcon Glyph="&#xE928;"
FontSize="27"
Foreground="{ThemeResource KronaTextInverseBrush}" />
</Border>
</Grid>
<TextBlock Text="Приложите палец"
Foreground="{ThemeResource KronaTextPrimaryBrush}"
Style="{StaticResource TitleTextBlockStyle}"
HorizontalAlignment="Center"/>
<TextBlock x:Name="TerminalMessage"
MaxWidth="360"
Foreground="{ThemeResource KronaTextSecondaryBrush}"
Text="Ожидание сканирования"
TextWrapping="Wrap"
TextAlignment="Center"/>
</StackPanel>
</Border>
<Grid Grid.Column="1" RowSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="Последние отметки"
Foreground="{ThemeResource KronaTextPrimaryBrush}"
Style="{StaticResource SubtitleTextBlockStyle}"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
<Button Content="Экспорт CSV" Click="ExportAttendance_Click" />
<Button Content="Очистить журнал" Click="ClearAttendance_Click" />
</StackPanel>
</Grid>
<ListView x:Name="AttendanceList"
Grid.Row="1"
Background="{ThemeResource KronaRaisedSurfaceBrush}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:AttendanceRecord">
<Grid Padding="4,10" ColumnSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="160"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind EmployeeName}" FontWeight="SemiBold"/>
<TextBlock Grid.Column="1" Text="{x:Bind EventType}" FontWeight="SemiBold"/>
<TextBlock Grid.Column="2" Text="{x:Bind LocalTime}"/>
<TextBlock Grid.Column="3" Text="{x:Bind DeliveryStatus}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</TabViewItem>
<TabViewItem x:Name="EmployeesTab" Header="Сотрудники" IsClosable="False">
<Grid Padding="4,16,4,4" RowSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Добавление и регистрация сотрудников" Foreground="{ThemeResource KronaTextPrimaryBrush}" Style="{StaticResource SubtitleTextBlockStyle}"/>
<CommandBar Grid.Row="1" Background="{ThemeResource KronaSurfaceBrush}" DefaultLabelPosition="Right">
<AppBarButton Icon="Add" Label="Добавить" Click="AddEmployee_Click"/>
<AppBarButton Icon="Edit" Label="Редактировать" Click="EditEmployee_Click"/>
<AppBarButton Icon="Contact" Label="Добавить отпечаток" Click="RegisterFingerprint_Click"/>
<AppBarButton Icon="Cancel" Label="Отменить регистрацию" Click="CancelRegistration_Click"/>
<AppBarButton Label="Удалить отпечатки" Click="DeleteFingerprints_Click">
<AppBarButton.Icon>
<FontIcon Glyph="&#xE928;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton Icon="Permissions" Label="Права администратора" Click="ToggleAdministrator_Click"/>
<AppBarButton Icon="Message" Label="Личные уведомления" Click="EditEmployeeNotifications_Click"/>
<AppBarButton Icon="BlockContact" Label="Блок./разблок." Click="ToggleEmployeeBlocked_Click"/>
<AppBarButton Icon="Delete" Label="Удалить" Click="DeleteEmployee_Click"/>
<AppBarSeparator />
<AppBarButton Label="Заблокировать" Click="LogoutAdmin_Click">
<AppBarButton.Icon>
<FontIcon Glyph="&#xE72E;" />
</AppBarButton.Icon>
</AppBarButton>
</CommandBar>
<Grid Grid.Row="2" ColumnSpacing="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Spacing="10">
<TextBox x:Name="PersonnelNumberBox" Header="Табельный номер" PlaceholderText="Например, 001" AutomationProperties.Name="Табельный номер"/>
<TextBox x:Name="EmployeeNameBox" Header="Имя сотрудника" PlaceholderText="Иван Петров" AutomationProperties.Name="Имя сотрудника"/>
<TextBox x:Name="PositionBox" Header="Должность" PlaceholderText="Например, менеджер" AutomationProperties.Name="Должность"/>
<ComboBox x:Name="GenderComboBox" Header="Пол" SelectedIndex="0">
<ComboBoxItem Content="Не указан" />
<ComboBoxItem Content="Мужской" />
<ComboBoxItem Content="Женский" />
</ComboBox>
<CheckBox x:Name="AdministratorCheckBox" Content="Администратор терминала"/>
<TextBlock Text="Выберите сотрудника справа и нажмите «Добавить отпечаток». Для каждого нового пальца повторите регистрацию из трёх сканов." TextWrapping="Wrap" Opacity="0.75"/>
</StackPanel>
<ListView x:Name="EmployeesList" Grid.Column="1" Background="{ThemeResource KronaRaisedSurfaceBrush}" SelectionMode="Single" SelectionChanged="EmployeesList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:EmployeeRecord">
<Grid Padding="4,10" ColumnSpacing="14">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="170"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind PersonnelNumber}"/>
<TextBlock Grid.Column="1" Text="{x:Bind DisplayName}" FontWeight="SemiBold"/>
<TextBlock Grid.Column="2" Text="{x:Bind Position}"/>
<TextBlock Grid.Column="3" Text="{x:Bind GenderDisplay}"/>
<TextBlock Grid.Column="4" Text="{x:Bind AccessStatus}"/>
<TextBlock Grid.Column="5" Text="{x:Bind FingerprintStatus}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</TabViewItem>
<TabViewItem x:Name="SettingsTab" Header="Уведомления и сканер" IsClosable="False">
<ScrollViewer>
<StackPanel Padding="4,16,20,24" Spacing="14" MaxWidth="720" HorizontalAlignment="Left">
<TextBlock Text="Сканер" Foreground="{ThemeResource KronaTextPrimaryBrush}" Style="{StaticResource SubtitleTextBlockStyle}"/>
<Grid ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="ReaderCombo"
Header="Используемое устройство"
MinWidth="320"
SelectionChanged="ReaderCombo_SelectionChanged"/>
<Button Grid.Column="1"
Content="Найти сканеры"
VerticalAlignment="Bottom"
Click="ScanReaders_Click"/>
</Grid>
<ToggleSwitch x:Name="StartWithWindowsSwitch" Header="Автозагрузка" OffContent="Выключена" OnContent="Запускать вместе с Windows"/>
<NumberBox x:Name="DuplicateGuardBox" Header="Защита от повторного скана, секунд" Minimum="10" Maximum="3600" SpinButtonPlacementMode="Compact"/>
<NumberBox x:Name="MaximumShiftHoursBox" Header="Максимальная длительность смены, часов" Minimum="1" Maximum="48" SpinButtonPlacementMode="Compact"/>
<ToggleSwitch x:Name="ShowEmployeeNamesSwitch" Header="Имена в публичном журнале терминала" OffContent="Скрыты" OnContent="Показывать"/>
<PasswordBox x:Name="NewAdminPinBox" Header="Новый PIN администратора" PasswordRevealMode="Peek"/>
<Button Content="Установить новый PIN" HorizontalAlignment="Left" Click="SetAdminPin_Click"/>
<Border Height="1" Background="{ThemeResource DividerStrokeColorDefaultBrush}"/>
<ToggleSwitch x:Name="TelegramEnabledSwitch" Header="Telegram" OffContent="Выключен" OnContent="Включён"/>
<PasswordBox x:Name="TelegramTokenBox" Header="Токен Telegram-бота" PasswordRevealMode="Peek"/>
<TextBlock Text="Личный chat_id задаётся в карточке каждого сотрудника." TextWrapping="Wrap" Opacity="0.7"/>
<Border Height="1" Background="{ThemeResource DividerStrokeColorDefaultBrush}"/>
<ToggleSwitch x:Name="VkEnabledSwitch" Header="ВКонтакте" OffContent="Выключен" OnContent="Включён"/>
<PasswordBox x:Name="VkTokenBox" Header="Токен сообщества ВКонтакте" PasswordRevealMode="Peek"/>
<TextBlock Text="Личный peer_id задаётся в карточке сотрудника. Сотрудник должен разрешить сообщения сообщества." TextWrapping="Wrap" Opacity="0.7"/>
<Border Height="1" Background="{ThemeResource DividerStrokeColorDefaultBrush}"/>
<ToggleSwitch x:Name="MaxEnabledSwitch" Header="MAX" OffContent="Выключен" OnContent="Включён"/>
<PasswordBox x:Name="MaxTokenBox" Header="Токен MAX-бота" PasswordRevealMode="Peek"/>
<TextBlock Text="Личный user_id задаётся в карточке каждого сотрудника." TextWrapping="Wrap" Opacity="0.7"/>
<Border Height="1" Background="{ThemeResource DividerStrokeColorDefaultBrush}"/>
<TextBlock Text="Обновления программы" Foreground="{ThemeResource KronaTextPrimaryBrush}" Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock x:Name="CurrentVersionText" Opacity="0.75"/>
<ToggleSwitch x:Name="UpdateChecksSwitch"
Header="Автоматическая проверка"
OffContent="Выключена"
OnContent="Проверять при запуске и каждые 6 часов"/>
<TextBox x:Name="UpdateFeedBox"
Header="Адрес канала обновлений"
IsReadOnly="True"
PlaceholderText="HTTPS-адрес последнего релиза"/>
<PasswordBox x:Name="UpdateTokenBox"
Header="Токен чтения приватного репозитория"
PasswordRevealMode="Peek"/>
<TextBlock Text="Токен нужен только пока обновления берутся из приватного Forgejo. Позже этот канал можно заменить Бизнес Платформой без изменения установщика."
TextWrapping="Wrap"
Opacity="0.7"/>
<Button Content="Проверить обновления"
HorizontalAlignment="Left"
Click="CheckForUpdates_Click"/>
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Сохранить настройки"
Background="{ThemeResource KronaPrimaryBrush}"
Foreground="{ThemeResource KronaTextInverseBrush}"
Click="SaveSettings_Click"/>
<Button Content="Тест выбранному сотруднику" Click="TestNotification_Click"/>
<Button Content="Заблокировать" Click="LogoutAdmin_Click"/>
</StackPanel>
<TextBlock Text="Токены, сотрудники и шаблоны отпечатков хранятся в зашифрованном хранилище текущей учётной записи Windows." TextWrapping="Wrap" Opacity="0.7"/>
</StackPanel>
</ScrollViewer>
</TabViewItem>
</TabView>
</Grid>
<Grid x:Name="ApplicationLockScreen"
Padding="32"
Background="{ThemeResource KronaAppBackgroundBrush}">
<Border Width="460"
Padding="40"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{ThemeResource KronaSurfaceBrush}"
BorderBrush="{ThemeResource KronaBorderBrush}"
BorderThickness="1"
CornerRadius="{StaticResource KronaRadiusLarge}">
<StackPanel Spacing="18">
<Image Width="120" Height="120" Source="Assets/TrushenkoLogo.png" Stretch="Uniform"/>
<TextBlock Text="Krona Staff заблокирован"
Style="{StaticResource TitleTextBlockStyle}"
TextAlignment="Center"/>
<TextBlock x:Name="LockScreenMessage"
Text="Введите PIN администратора или приложите зарегистрированный палец."
TextWrapping="Wrap"
TextAlignment="Center"
Opacity="0.75"/>
<PasswordBox x:Name="UnlockPinBox"
Header="PIN администратора"
PasswordRevealMode="Peek"
KeyDown="UnlockPinBox_KeyDown"/>
<Button Content="Войти"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Background="{ThemeResource KronaPrimaryBrush}"
Foreground="{ThemeResource KronaTextInverseBrush}"
Click="UnlockApplication_Click"/>
<TextBlock Text="До входа сотрудники, журнал и настройки скрыты."
TextAlignment="Center"
Opacity="0.6"/>
</StackPanel>
</Border>
</Grid>
</Grid>
</Page>