LSFE/LSFE.MobApp/Pages/Utilities/UtilitiesPage.xaml
2026-07-30 10:31:04 +08:00

382 lines
19 KiB
XML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:LSFE.MobApp.ViewModels.Utility"
x:Class="LSFE.MobApp.Pages.Utilities.UtilitiesPage"
x:DataType="vm:UtilitiesVM"
Title="Sync Utilities"
BackgroundColor="#F3F4F6">
<ContentPage.Resources>
<ResourceDictionary>
<Shadow x:Key="CardShadow"
Brush="Black"
Opacity="0.1"
Radius="12"
Offset="0,4" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<!-- Main Content -->
<Grid RowDefinitions="Auto,*,Auto" Padding="0">
<!-- Header Section -->
<Border Grid.Row="0"
BackgroundColor="#6366F1"
Padding="20,18,20,22">
<Border.StrokeShape>
<RoundRectangle CornerRadius="0,0,24,24" />
</Border.StrokeShape>
<Grid RowDefinitions="Auto,Auto,Auto" ColumnSpacing="10">
<!-- Row 0: Title + Crash Log Button -->
<Grid Grid.Row="0" ColumnDefinitions="*,Auto">
<Label Grid.Column="0"
Text="Data Synchronization"
FontSize="24"
FontAttributes="Bold"
TextColor="White"
VerticalOptions="Center" />
<Border Grid.Column="1"
BackgroundColor="#00000033"
WidthRequest="40"
HeightRequest="40"
StrokeThickness="0"
VerticalOptions="Center">
<Border.StrokeShape>
<RoundRectangle CornerRadius="10" />
</Border.StrokeShape>
<Border.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ViewCrashLogCommand}" />
</Border.GestureRecognizers>
<Label Text="📜"
FontSize="18"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Border>
</Grid>
<!-- Row 1: Network Status Bar -->
<Border Grid.Row="1"
BackgroundColor="#00000026"
Padding="12,8"
StrokeThickness="0">
<Border.StrokeShape>
<RoundRectangle CornerRadius="10" />
</Border.StrokeShape>
<Border.GestureRecognizers>
<TapGestureRecognizer Command="{Binding RefreshNetworkCommand}" />
</Border.GestureRecognizers>
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="10">
<Label Grid.Column="0"
Text="{Binding NetworkIcon}"
FontSize="16"
VerticalOptions="Center" />
<Label Grid.Column="1"
Text="{Binding NetworkStatusText}"
FontSize="13"
FontAttributes="Bold"
TextColor="{Binding NetworkStatusColor}"
VerticalOptions="Center" />
<ActivityIndicator Grid.Column="2"
IsRunning="{Binding IsCheckingNetwork}"
IsVisible="{Binding IsCheckingNetwork}"
Color="White"
WidthRequest="16"
HeightRequest="16"
VerticalOptions="Center" />
<Label Grid.Column="2"
IsVisible="{Binding IsCheckingNetwork, Converter={StaticResource InverseBoolConverter}}"
Text="↻"
FontSize="16"
TextColor="#FFFFFFCC"
VerticalOptions="Center"
HorizontalOptions="Center" />
</Grid>
</Border>
<!-- Row 2: Sync Status + Last Synced -->
<VerticalStackLayout Grid.Row="2" Spacing="2">
<Label Text="{Binding SyncStatus}"
FontSize="13"
TextColor="White"
Opacity="0.9" />
<Label IsVisible="{Binding LastSyncTime, Converter={StaticResource IsNotNullConverter}}"
FontSize="11"
TextColor="White"
Opacity="0.65">
<Label.FormattedText>
<FormattedString>
<Span Text="Last synced: " />
<Span Text="{Binding LastSyncTime, StringFormat='{0:MMM dd, yyyy h:mm tt}'}" />
</FormattedString>
</Label.FormattedText>
</Label>
</VerticalStackLayout>
</Grid>
</Border>
<!-- Sync Items List -->
<ScrollView Grid.Row="1" Padding="16,16">
<VerticalStackLayout Spacing="12">
<!-- Sync All Button -->
<Border BackgroundColor="White"
StrokeThickness="0"
Padding="18"
Shadow="{StaticResource CardShadow}">
<Border.StrokeShape>
<RoundRectangle CornerRadius="16" />
</Border.StrokeShape>
<Border.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SyncAllCommand}" />
</Border.GestureRecognizers>
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="14">
<Border Grid.Column="0"
WidthRequest="52"
HeightRequest="52"
BackgroundColor="#ffa500"
StrokeThickness="0">
<Border.StrokeShape>
<RoundRectangle CornerRadius="13" />
</Border.StrokeShape>
<Label Text="⟳"
FontSize="28"
TextColor="White"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Border>
<VerticalStackLayout Grid.Column="1"
VerticalOptions="Center"
Spacing="2">
<Label Text="Sync All Data"
FontSize="16"
FontAttributes="Bold"
TextColor="#111827" />
<Label Text="Synchronize all modules at once"
FontSize="12"
TextColor="#6B7280" />
</VerticalStackLayout>
<Label Grid.Column="2"
Text=""
FontSize="26"
TextColor="#9CA3AF"
VerticalOptions="Center" />
</Grid>
</Border>
<!-- Individual Sync Items -->
<CollectionView ItemsSource="{Binding SyncItems}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="vm:SyncItem">
<Border BackgroundColor="White"
StrokeThickness="0"
Padding="16"
Margin="0,0,0,10"
Shadow="{StaticResource CardShadow}">
<Border.StrokeShape>
<RoundRectangle CornerRadius="16" />
</Border.StrokeShape>
<Border.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type vm:UtilitiesVM}},
Path=SyncItemCommand}"
CommandParameter="{Binding .}" />
</Border.GestureRecognizers>
<Grid ColumnDefinitions="Auto,*,Auto"
RowDefinitions="Auto,Auto"
ColumnSpacing="14">
<!-- Icon Circle -->
<Border Grid.Column="0"
Grid.RowSpan="2"
WidthRequest="48"
HeightRequest="48"
BackgroundColor="{Binding IconColor,
Converter={StaticResource ColorToLightColorConverter}}"
StrokeThickness="0"
VerticalOptions="Center">
<Border.StrokeShape>
<RoundRectangle CornerRadius="12" />
</Border.StrokeShape>
<Label FontSize="22"
TextColor="{Binding IconColor}"
HorizontalOptions="Center"
VerticalOptions="Center">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding Title}"
Value="Attendance logs">
<Setter Property="Text" Value="⏰" />
</DataTrigger>
<DataTrigger TargetType="Label"
Binding="{Binding Title}"
Value="Coverage Plan">
<Setter Property="Text" Value="📅" />
</DataTrigger>
<DataTrigger TargetType="Label"
Binding="{Binding Title}"
Value="Actual Coverage">
<Setter Property="Text" Value="🏥" />
</DataTrigger>
<DataTrigger TargetType="Label"
Binding="{Binding Title}"
Value="Error logs">
<Setter Property="Text" Value="🚨" />
</DataTrigger>
</Label.Triggers>
</Label>
</Border>
<!-- Title -->
<Label Grid.Column="1"
Grid.Row="0"
Text="{Binding Title}"
FontSize="15"
FontAttributes="Bold"
TextColor="#111827"
VerticalOptions="End" />
<!-- Description -->
<Label Grid.Column="1"
Grid.Row="1"
Text="{Binding Description}"
FontSize="12"
TextColor="#6B7280"
VerticalOptions="Start" />
<!-- Status/Loading -->
<VerticalStackLayout Grid.Column="2"
Grid.RowSpan="2"
VerticalOptions="Center"
HorizontalOptions="End"
Spacing="3">
<ActivityIndicator IsRunning="{Binding IsSyncing}"
IsVisible="{Binding IsSyncing}"
Color="{Binding IconColor}"
WidthRequest="20"
HeightRequest="20" />
<Label Text="{Binding Status}"
IsVisible="{Binding Status,
Converter={StaticResource IsNotNullOrEmptyConverter}}"
FontSize="11"
FontAttributes="Bold"
TextColor="{Binding IconColor}"
HorizontalOptions="End" />
<Label IsVisible="{Binding LastSynced,
Converter={StaticResource IsNotNullConverter}}"
FontSize="10"
TextColor="#6B7280"
HorizontalOptions="End"
Text="{Binding LastSynced, StringFormat='{0:hh:mm tt}'}" />
</VerticalStackLayout>
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
<!-- Bottom Info Section -->
<Border Grid.Row="2"
BackgroundColor="White"
StrokeThickness="0"
Padding="20,14">
<Border.StrokeShape>
<RoundRectangle CornerRadius="24,24,0,0" />
</Border.StrokeShape>
<HorizontalStackLayout Spacing="8" HorizontalOptions="Center">
<Label Text=""
FontSize="14"
VerticalOptions="Center" />
<Label Text="Tap any item to sync individually"
FontSize="13"
TextColor="#6B7280"
VerticalOptions="Center" />
</HorizontalStackLayout>
</Border>
</Grid>
<!-- Loading Overlay -->
<Grid BackgroundColor="#80000000"
IsVisible="{Binding IsSyncing}"
InputTransparent="False">
<Grid.GestureRecognizers>
<TapGestureRecognizer />
</Grid.GestureRecognizers>
<Border StrokeShape="RoundRectangle 20"
BackgroundColor="White"
Padding="40,32"
MaximumWidthRequest="280"
MaximumHeightRequest="200"
HorizontalOptions="Center"
VerticalOptions="Center"
Shadow="{StaticResource CardShadow}">
<VerticalStackLayout Spacing="20"
HorizontalOptions="Center"
VerticalOptions="Center">
<Border WidthRequest="55"
HeightRequest="55"
BackgroundColor="#E0F2FE"
StrokeThickness="0"
HorizontalOptions="Center">
<Border.StrokeShape>
<RoundRectangle CornerRadius="32" />
</Border.StrokeShape>
<ActivityIndicator IsRunning="True"
Color="#0EA5E9"
WidthRequest="30"
HeightRequest="30"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Border>
<VerticalStackLayout Spacing="8" HorizontalOptions="Center">
<Label Text="Synchronizing..."
TextColor="#0EA5E9"
FontAttributes="Bold"
FontSize="18"
HorizontalOptions="Center"
HorizontalTextAlignment="Center" />
<Label Text="Please wait"
TextColor="#6B7280"
FontSize="14"
HorizontalOptions="Center"
HorizontalTextAlignment="Center" />
</VerticalStackLayout>
</VerticalStackLayout>
</Border>
</Grid>
</Grid>
</ContentPage>