feat(sprint-3): apply Survey Teal field UI
This commit is contained in:
@@ -5,80 +5,163 @@
|
||||
xmlns:models="clr-namespace:FieldLogger.Models"
|
||||
x:Class="FieldLogger.Views.HomePage"
|
||||
x:DataType="vm:HomeViewModel"
|
||||
Title="Field Logger">
|
||||
Title="Field Logger"
|
||||
BackgroundColor="{DynamicResource UlColorCanvas}">
|
||||
<ScrollView>
|
||||
<VerticalStackLayout Padding="16" Spacing="12">
|
||||
<VerticalStackLayout Padding="16" Spacing="16">
|
||||
<VerticalStackLayout Spacing="4">
|
||||
<Label Text="FIELD LOGGER" FontSize="14" FontAttributes="Bold" CharacterSpacing="1.5"
|
||||
TextColor="{DynamicResource UlColorPrimary}" />
|
||||
<Label Text="Live field capture" Style="{StaticResource UlPageTitle}"
|
||||
TextColor="{DynamicResource UlColorText}"
|
||||
SemanticProperties.HeadingLevel="Level1" />
|
||||
</VerticalStackLayout>
|
||||
|
||||
<!-- Device connection status -->
|
||||
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
|
||||
<Grid ColumnDefinitions="16,*,Auto" RowDefinitions="Auto,Auto" RowSpacing="10" ColumnSpacing="10">
|
||||
<Ellipse Grid.Row="0" Grid.Column="0" WidthRequest="12" HeightRequest="12" VerticalOptions="Center"
|
||||
Fill="{Binding Manager.LocatorState, Converter={StaticResource StateColor}}" />
|
||||
<VerticalStackLayout Grid.Row="0" Grid.Column="1" Spacing="0">
|
||||
<Label Text="{Binding Manager.LocatorName, TargetNullValue='Locating Receiver — not selected'}" FontAttributes="Bold" />
|
||||
<Label Text="{Binding Manager.LocatorState, Converter={StaticResource StateText}}" FontSize="12" TextColor="Gray" />
|
||||
</VerticalStackLayout>
|
||||
<Button Grid.Row="0" Grid.Column="2" Text="Select" FontSize="12" Padding="10,4"
|
||||
Command="{Binding SelectLocatorCommand}" />
|
||||
|
||||
<Ellipse Grid.Row="1" Grid.Column="0" WidthRequest="12" HeightRequest="12" VerticalOptions="Center"
|
||||
Fill="{Binding Manager.GpsState, Converter={StaticResource StateColor}}" />
|
||||
<VerticalStackLayout Grid.Row="1" Grid.Column="1" Spacing="0">
|
||||
<Label Text="{Binding Manager.GpsName, TargetNullValue='Maglink RTK GPS — not selected'}" FontAttributes="Bold" />
|
||||
<Label Text="{Binding Manager.GpsState, Converter={StaticResource StateText}}" FontSize="12" TextColor="Gray" />
|
||||
</VerticalStackLayout>
|
||||
<Button Grid.Row="1" Grid.Column="2" Text="Select" FontSize="12" Padding="10,4"
|
||||
Command="{Binding SelectGpsCommand}" />
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeThickness="1"
|
||||
StrokeShape="RoundRectangle 12" Padding="16"
|
||||
SemanticProperties.Description="Active job and local capture count">
|
||||
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="*,Auto" RowSpacing="8" ColumnSpacing="12">
|
||||
<Label Text="ACTIVE JOB" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Label Grid.Row="1" Text="{Binding ActiveJobName}" FontSize="22" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorText}" LineBreakMode="TailTruncation" />
|
||||
<Label Grid.Row="2" Text="{Binding ActiveJobPointSummary}" FontSize="16"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Button Grid.RowSpan="3" Grid.Column="1" Style="{StaticResource UlButtonSecondary}"
|
||||
Text="Jobs" Command="{Binding SelectJobCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchMinimum}" MinimumWidthRequest="72" FontAttributes="Bold"
|
||||
SemanticProperties.Description="Choose or review the active job" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Live GNSS fix -->
|
||||
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
|
||||
<VerticalStackLayout Spacing="4">
|
||||
<HorizontalStackLayout Spacing="8">
|
||||
<Label Text="GPS" FontAttributes="Bold" />
|
||||
<Label Text="{Binding FixStatusLabel}" TextColor="DodgerBlue" FontAttributes="Bold" />
|
||||
</HorizontalStackLayout>
|
||||
<Label Text="{Binding FixSummary}" FontFamily="Courier New" FontSize="13" />
|
||||
<Label Text="{Binding FixAccuracy}" FontSize="12" TextColor="Gray" />
|
||||
</VerticalStackLayout>
|
||||
<!-- Production capture remains receiver-triggered. This is deliberately guidance,
|
||||
not an app button that would invent an unsupported device command. -->
|
||||
<Border BackgroundColor="{DynamicResource UlColorPrimary}" StrokeThickness="0"
|
||||
StrokeShape="RoundRectangle 20" Padding="20,16" MinimumHeightRequest="{StaticResource UlTouchPrimary}"
|
||||
SemanticProperties.Description="Hardware capture action. Press the log button on the locating receiver.">
|
||||
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="12">
|
||||
<Label Text="◎" FontSize="30" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorOnPrimary}" VerticalTextAlignment="Center" />
|
||||
<VerticalStackLayout Grid.Column="1" Spacing="2" VerticalOptions="Center">
|
||||
<Label Text="CAPTURE FROM RECEIVER" FontSize="18" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorOnPrimary}" />
|
||||
<Label Text="{Binding CaptureReadinessText}" FontSize="14"
|
||||
TextColor="{DynamicResource UlColorOnPrimary}" />
|
||||
</VerticalStackLayout>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Active job -->
|
||||
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}" StrokeShape="RoundRectangle 12" Padding="12">
|
||||
<Button Style="{StaticResource UlButtonPrimaryField}"
|
||||
Text="Choose an active job" IsVisible="{Binding HasNoActiveJob}"
|
||||
Command="{Binding SelectJobCommand}" MinimumHeightRequest="{StaticResource UlTouchComfortable}" FontAttributes="Bold"
|
||||
SemanticProperties.Description="Capture is blocked. Choose or create an active job." />
|
||||
|
||||
<Label Text="DEVICE STATUS" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}"
|
||||
SemanticProperties.HeadingLevel="Level2" />
|
||||
<Grid ColumnDefinitions="*,*" ColumnSpacing="8">
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12"
|
||||
Padding="12" MinimumHeightRequest="96">
|
||||
<VerticalStackLayout Spacing="4">
|
||||
<Label Text="LOCATOR" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Label Text="{Binding Manager.LocatorName, TargetNullValue='Not selected'}"
|
||||
FontSize="16" FontAttributes="Bold" TextColor="{DynamicResource UlColorText}"
|
||||
LineBreakMode="TailTruncation" />
|
||||
<Label Text="{Binding Manager.LocatorState, Converter={StaticResource StateText}}"
|
||||
FontSize="14" TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Button Style="{StaticResource UlButtonSecondary}"
|
||||
Text="Select locator" Command="{Binding SelectLocatorCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchMinimum}" Margin="0,4,0,0"
|
||||
SemanticProperties.Description="Select the locating receiver" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
<Border Grid.Column="1" Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12"
|
||||
Padding="12" MinimumHeightRequest="96">
|
||||
<VerticalStackLayout Spacing="4">
|
||||
<Label Text="RTK GPS" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Label Text="{Binding Manager.GpsName, TargetNullValue='Not selected'}"
|
||||
FontSize="16" FontAttributes="Bold" TextColor="{DynamicResource UlColorText}"
|
||||
LineBreakMode="TailTruncation" />
|
||||
<Label Text="{Binding Manager.GpsState, Converter={StaticResource StateText}}"
|
||||
FontSize="14" TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Button Style="{StaticResource UlButtonSecondary}"
|
||||
Text="Select GPS" Command="{Binding SelectGpsCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchMinimum}" Margin="0,4,0,0"
|
||||
SemanticProperties.Description="Select the Maglink RTK GPS receiver" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12" Padding="16">
|
||||
<VerticalStackLayout Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<VerticalStackLayout Spacing="0">
|
||||
<Label Text="{Binding ActiveJobName}" FontAttributes="Bold" FontSize="16" />
|
||||
<Label FontSize="12" TextColor="Gray">
|
||||
<Label.Text>
|
||||
<Binding Path="PointCount" StringFormat="{}{0} points logged" />
|
||||
</Label.Text>
|
||||
</Label>
|
||||
</VerticalStackLayout>
|
||||
<HorizontalStackLayout Grid.Column="1" Spacing="6">
|
||||
<Button Text="New Job" FontSize="12" Padding="10,4" Command="{Binding NewJobCommand}" />
|
||||
<Button Text="Jobs" FontSize="12" Padding="10,4" Command="{Binding SelectJobCommand}" />
|
||||
</HorizontalStackLayout>
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="12">
|
||||
<Label Text="POSITION FIX" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Label Grid.Column="1" Text="{Binding FixStatusLabel}" FontSize="16" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorText}"
|
||||
SemanticProperties.Description="Current GPS fix quality" />
|
||||
</Grid>
|
||||
<Label Text="Press the log button on the receiver to capture a point."
|
||||
FontSize="12" TextColor="Gray" IsVisible="{Binding HasActiveJob}" />
|
||||
<Label Text="{Binding SyncStatus}" FontSize="11" TextColor="DodgerBlue" />
|
||||
<Label Text="{Binding FixSummary}" FontSize="18" FontFamily="{StaticResource UlTypeFamilyMono}"
|
||||
TextColor="{DynamicResource UlColorText}" />
|
||||
<Label Text="{Binding FixAccuracy}" FontSize="14"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Recent points -->
|
||||
<Label Text="Recent Points" FontAttributes="Bold" Margin="4,8,0,0" />
|
||||
<CollectionView ItemsSource="{Binding RecentPoints}" HeightRequest="320">
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12" Padding="16">
|
||||
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="10">
|
||||
<Label Text="↕" FontSize="22" TextColor="{DynamicResource UlColorPrimary}" />
|
||||
<VerticalStackLayout Grid.Column="1" Spacing="2">
|
||||
<Label Text="SYNC STATUS" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Label Text="{Binding SyncStatus}" FontSize="16" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorText}"
|
||||
SemanticProperties.Description="Current synchronization status" />
|
||||
</VerticalStackLayout>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<Label Text="RECENT CAPTURES" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorTextMuted}"
|
||||
SemanticProperties.HeadingLevel="Level2" />
|
||||
<Button Grid.Column="1" Style="{StaticResource UlButtonSecondary}"
|
||||
Text="View map" Command="{Binding ViewMapCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchMinimum}" MinimumWidthRequest="96"
|
||||
SemanticProperties.Description="View captured points on the map" />
|
||||
</Grid>
|
||||
|
||||
<CollectionView ItemsSource="{Binding RecentPoints}" HeightRequest="360"
|
||||
SemanticProperties.Description="Ten most recent locally saved capture points">
|
||||
<CollectionView.EmptyView>
|
||||
<Label Text="No points logged yet." TextColor="Gray" Margin="8" />
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}"
|
||||
StrokeShape="RoundRectangle 12" Padding="20">
|
||||
<VerticalStackLayout Spacing="6">
|
||||
<Label Text="No captures yet" Style="{StaticResource UlEmptyStateTitle}"
|
||||
HorizontalTextAlignment="Center" TextColor="{DynamicResource UlColorText}" />
|
||||
<Label Text="With an active job, press LOG on the receiver to save the first point."
|
||||
Style="{StaticResource UlEmptyStateBody}"
|
||||
FontSize="14" HorizontalTextAlignment="Center"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
</CollectionView.EmptyView>
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:LoggedPoint">
|
||||
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#FAFAFA, Dark=#242426}"
|
||||
StrokeShape="RoundRectangle 8" Padding="10" Margin="0,2">
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto">
|
||||
<Label Grid.Row="0" FontSize="13" FontAttributes="Bold">
|
||||
<Border Style="{StaticResource UlJobRow}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}"
|
||||
StrokeShape="RoundRectangle 12" Padding="12" Margin="0,0,0,8"
|
||||
MinimumHeightRequest="76">
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto" RowSpacing="6" ColumnSpacing="12">
|
||||
<Label FontSize="16" FontAttributes="Bold" TextColor="{DynamicResource UlColorText}">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="{}{0} · {1} Hz · depth {2}">
|
||||
<Binding Path="Utility" Converter="{StaticResource UtilityName}" />
|
||||
@@ -87,9 +170,10 @@
|
||||
</MultiBinding>
|
||||
</Label.Text>
|
||||
</Label>
|
||||
<Label Grid.Row="0" Grid.Column="1" FontSize="12" TextColor="Gray"
|
||||
<Label Grid.Column="1" FontSize="14" TextColor="{DynamicResource UlColorTextMuted}"
|
||||
Text="{Binding TimestampUtc, StringFormat='{0:HH:mm:ss}'}" />
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="12" TextColor="Gray">
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="14" FontFamily="{StaticResource UlTypeFamilyMono}"
|
||||
TextColor="{DynamicResource UlColorTextMuted}">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="{}{0:F7}, {1:F7} · {2}">
|
||||
<Binding Path="Latitude" />
|
||||
@@ -103,7 +187,6 @@
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
|
||||
@@ -5,37 +5,64 @@
|
||||
xmlns:models="clr-namespace:FieldLogger.Models"
|
||||
x:Class="FieldLogger.Views.JobDetailPage"
|
||||
x:DataType="vm:JobDetailViewModel"
|
||||
Title="{Binding JobName}">
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Map" Command="{Binding ViewMapCommand}" />
|
||||
</ContentPage.ToolbarItems>
|
||||
Title="{Binding JobName}"
|
||||
BackgroundColor="{DynamicResource UlColorCanvas}">
|
||||
<Grid RowDefinitions="Auto,*" Padding="16" RowSpacing="16">
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12" Padding="16">
|
||||
<Grid RowDefinitions="Auto,Auto" ColumnDefinitions="*,Auto" RowSpacing="6" ColumnSpacing="12">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="JOB DETAIL" FontSize="14" FontAttributes="Bold" CharacterSpacing="1.5"
|
||||
TextColor="{DynamicResource UlColorPrimary}" />
|
||||
<Label Text="{Binding JobName}" Style="{StaticResource UlPageTitle}"
|
||||
TextColor="{DynamicResource UlColorText}" LineBreakMode="TailTruncation"
|
||||
SemanticProperties.HeadingLevel="Level1" />
|
||||
</VerticalStackLayout>
|
||||
<Button Grid.Column="1" Style="{StaticResource UlButtonSecondary}"
|
||||
Text="View map" Command="{Binding ViewMapCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchMinimum}" MinimumWidthRequest="96"
|
||||
SemanticProperties.Description="View this job's captured points on the map" />
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="16"
|
||||
TextColor="{DynamicResource UlColorTextMuted}"
|
||||
Text="{Binding PointCount, StringFormat='{0} locally logged points'}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Grid RowDefinitions="Auto,*" Padding="16" RowSpacing="8">
|
||||
<Label Grid.Row="0" FontSize="13" TextColor="Gray"
|
||||
Text="{Binding PointCount, StringFormat='{0} logged points'}" />
|
||||
|
||||
<CollectionView Grid.Row="1" ItemsSource="{Binding Points}">
|
||||
<CollectionView Grid.Row="1" ItemsSource="{Binding Points}"
|
||||
SemanticProperties.Description="Captured points for this job">
|
||||
<CollectionView.EmptyView>
|
||||
<Label Text="No points logged for this job yet." TextColor="Gray" Margin="8" />
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}"
|
||||
StrokeShape="RoundRectangle 12" Padding="24">
|
||||
<VerticalStackLayout Spacing="8">
|
||||
<Label Text="No captures for this job" Style="{StaticResource UlEmptyStateTitle}"
|
||||
HorizontalTextAlignment="Center" TextColor="{DynamicResource UlColorText}" />
|
||||
<Label Text="Return Home and press LOG on the receiver when the job is active."
|
||||
Style="{StaticResource UlEmptyStateBody}"
|
||||
FontSize="16" HorizontalTextAlignment="Center"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
</CollectionView.EmptyView>
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:LoggedPoint">
|
||||
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}"
|
||||
StrokeShape="RoundRectangle 10" Padding="12" Margin="0,4">
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto,Auto,Auto" RowSpacing="2">
|
||||
<Label Grid.Row="0" FontAttributes="Bold" FontSize="14">
|
||||
<Border Style="{StaticResource UlJobRow}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12"
|
||||
Padding="16" Margin="0,0,0,12" MinimumHeightRequest="168">
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto,Auto,Auto" RowSpacing="8" ColumnSpacing="12">
|
||||
<Label FontSize="18" FontAttributes="Bold" TextColor="{DynamicResource UlColorText}">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="{}#{0} · {1} · {2} Hz">
|
||||
<MultiBinding StringFormat="{}Point #{0} · {1} · {2} Hz">
|
||||
<Binding Path="Id" />
|
||||
<Binding Path="Utility" Converter="{StaticResource UtilityName}" />
|
||||
<Binding Path="Frequency" />
|
||||
</MultiBinding>
|
||||
</Label.Text>
|
||||
</Label>
|
||||
<Label Grid.Row="0" Grid.Column="1" FontSize="12" TextColor="Gray"
|
||||
<Label Grid.Column="1" FontSize="14" TextColor="{DynamicResource UlColorTextMuted}"
|
||||
Text="{Binding TimestampUtc, StringFormat='{0:g}'}" />
|
||||
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="12">
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" FontSize="16"
|
||||
TextColor="{DynamicResource UlColorText}">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="Depth {0} · Current {1} · Signal {2} · Gain {3} dB">
|
||||
<Binding Path="DepthRaw" />
|
||||
@@ -45,8 +72,8 @@
|
||||
</MultiBinding>
|
||||
</Label.Text>
|
||||
</Label>
|
||||
|
||||
<Label Grid.Row="2" Grid.ColumnSpan="2" FontSize="12" FontFamily="Courier New">
|
||||
<Label Grid.Row="2" Grid.ColumnSpan="2" FontSize="16" FontFamily="{StaticResource UlTypeFamilyMono}"
|
||||
TextColor="{DynamicResource UlColorText}">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="{}{0:F8}, {1:F8}">
|
||||
<Binding Path="Latitude" />
|
||||
@@ -54,20 +81,22 @@
|
||||
</MultiBinding>
|
||||
</Label.Text>
|
||||
</Label>
|
||||
|
||||
<Label Grid.Row="3" FontSize="11" TextColor="Gray">
|
||||
<Label Grid.Row="3" FontSize="14" TextColor="{DynamicResource UlColorTextMuted}">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="{}{0} · H ±{1:F3} m · {2} sats">
|
||||
<MultiBinding StringFormat="{}{0} · H ±{1:F3} m · {2} satellites">
|
||||
<Binding Path="FixStatus" Converter="{StaticResource FixStatusName}" />
|
||||
<Binding Path="Hrms" />
|
||||
<Binding Path="SatellitesUsed" />
|
||||
</MultiBinding>
|
||||
</Label.Text>
|
||||
</Label>
|
||||
<Button Grid.Row="3" Grid.Column="1" Text="Delete" FontSize="11" Padding="8,2"
|
||||
BackgroundColor="Transparent" TextColor="IndianRed"
|
||||
<Button Grid.Row="3" Grid.Column="1" Style="{StaticResource UlButtonAccent}"
|
||||
Text="Delete point" MinimumHeightRequest="{StaticResource UlTouchMinimum}"
|
||||
BackgroundColor="{DynamicResource UlColorAccent}"
|
||||
TextColor="{DynamicResource UlColorOnAccent}"
|
||||
Command="{Binding DeletePointCommand, Source={RelativeSource AncestorType={x:Type vm:JobDetailViewModel}}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
CommandParameter="{Binding .}"
|
||||
SemanticProperties.Description="Delete this locally saved point" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -4,57 +4,91 @@
|
||||
xmlns:vm="clr-namespace:FieldLogger.ViewModels"
|
||||
x:Class="FieldLogger.Views.JobsPage"
|
||||
x:DataType="vm:JobsViewModel"
|
||||
Title="Jobs">
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="New" Command="{Binding NewJobCommand}" />
|
||||
</ContentPage.ToolbarItems>
|
||||
Title="Jobs"
|
||||
BackgroundColor="{DynamicResource UlColorCanvas}">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Padding="16" RowSpacing="16">
|
||||
<VerticalStackLayout Spacing="4">
|
||||
<Label Text="FIELD WORK" FontSize="14" FontAttributes="Bold" CharacterSpacing="1.5"
|
||||
TextColor="{DynamicResource UlColorPrimary}" />
|
||||
<Label Text="Jobs" Style="{StaticResource UlPageTitle}"
|
||||
TextColor="{DynamicResource UlColorText}"
|
||||
SemanticProperties.HeadingLevel="Level1" />
|
||||
<Label Text="Choose the active job before capturing points."
|
||||
FontSize="16" TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
</VerticalStackLayout>
|
||||
|
||||
<Grid Padding="16">
|
||||
<CollectionView ItemsSource="{Binding Jobs}">
|
||||
<CollectionView.EmptyView>
|
||||
<VerticalStackLayout Spacing="8" VerticalOptions="Center">
|
||||
<Label Text="No jobs yet." TextColor="Gray" HorizontalOptions="Center" />
|
||||
<Button Text="Create First Job" Command="{Binding NewJobCommand}" HorizontalOptions="Center" />
|
||||
</VerticalStackLayout>
|
||||
</CollectionView.EmptyView>
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:JobListItem">
|
||||
<Border StrokeThickness="0" Background="{AppThemeBinding Light=#F2F2F7, Dark=#1C1C1E}"
|
||||
StrokeShape="RoundRectangle 10" Padding="12" Margin="0,4">
|
||||
<Border.GestureRecognizers>
|
||||
<TapGestureRecognizer
|
||||
Command="{Binding OpenCommand, Source={RelativeSource AncestorType={x:Type vm:JobsViewModel}}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
</Border.GestureRecognizers>
|
||||
<Grid ColumnDefinitions="*,Auto,Auto" ColumnSpacing="8">
|
||||
<VerticalStackLayout Spacing="2">
|
||||
<HorizontalStackLayout Spacing="8">
|
||||
<Label Text="{Binding Name}" FontAttributes="Bold" />
|
||||
<Border IsVisible="{Binding IsActive}" Background="DodgerBlue"
|
||||
StrokeThickness="0" StrokeShape="RoundRectangle 6" Padding="6,1">
|
||||
<Label Text="ACTIVE" FontSize="10" TextColor="White" />
|
||||
</Border>
|
||||
</HorizontalStackLayout>
|
||||
<Label FontSize="12" TextColor="Gray">
|
||||
<Label.Text>
|
||||
<MultiBinding StringFormat="{}{0} · {1} points">
|
||||
<Binding Path="CreatedLabel" />
|
||||
<Binding Path="PointCount" />
|
||||
</MultiBinding>
|
||||
</Label.Text>
|
||||
</Label>
|
||||
</VerticalStackLayout>
|
||||
<Button Grid.Column="1" Text="Set Active" FontSize="12" Padding="10,4" VerticalOptions="Center"
|
||||
Command="{Binding SetActiveCommand, Source={RelativeSource AncestorType={x:Type vm:JobsViewModel}}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
<Button Grid.Column="2" Text="✕" FontSize="12" Padding="10,4" VerticalOptions="Center"
|
||||
BackgroundColor="IndianRed" TextColor="White"
|
||||
Command="{Binding DeleteCommand, Source={RelativeSource AncestorType={x:Type vm:JobsViewModel}}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
</Grid>
|
||||
<Button Grid.Row="1" Style="{StaticResource UlButtonPrimaryField}"
|
||||
Text="+ Create new job" Command="{Binding NewJobCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchComfortable}" FontSize="16" FontAttributes="Bold"
|
||||
SemanticProperties.Description="Create a new job and make it active" />
|
||||
|
||||
<RefreshView Grid.Row="2" Command="{Binding RefreshCommand}" IsRefreshing="{Binding IsBusy}">
|
||||
<CollectionView ItemsSource="{Binding Jobs}"
|
||||
SelectionMode="None"
|
||||
SemanticProperties.Description="Jobs available on this device">
|
||||
<CollectionView.EmptyView>
|
||||
<Border Style="{StaticResource UlCard}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}"
|
||||
StrokeShape="RoundRectangle 12" Padding="24">
|
||||
<VerticalStackLayout Spacing="8" VerticalOptions="Center">
|
||||
<Label Text="No jobs yet" Style="{StaticResource UlEmptyStateTitle}"
|
||||
HorizontalTextAlignment="Center" TextColor="{DynamicResource UlColorText}" />
|
||||
<Label Text="Create a job to establish the capture context."
|
||||
Style="{StaticResource UlEmptyStateBody}"
|
||||
FontSize="16" HorizontalTextAlignment="Center"
|
||||
TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Button Style="{StaticResource UlButtonPrimary}"
|
||||
Text="Create first job" Command="{Binding NewJobCommand}"
|
||||
MinimumHeightRequest="{StaticResource UlTouchComfortable}" HorizontalOptions="Fill"
|
||||
SemanticProperties.Description="Create the first job" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
</CollectionView.EmptyView>
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:JobListItem">
|
||||
<Border Style="{StaticResource UlJobRow}" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}"
|
||||
StrokeThickness="1" StrokeShape="RoundRectangle 12"
|
||||
Padding="16" Margin="0,0,0,12" MinimumHeightRequest="136"
|
||||
SemanticProperties.Description="{Binding AccessibilityDescription}"
|
||||
SemanticProperties.Hint="Double tap to open job details">
|
||||
<Border.GestureRecognizers>
|
||||
<TapGestureRecognizer
|
||||
Command="{Binding OpenCommand, Source={RelativeSource AncestorType={x:Type vm:JobsViewModel}}}"
|
||||
CommandParameter="{Binding .}" />
|
||||
</Border.GestureRecognizers>
|
||||
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="*,Auto" RowSpacing="8" ColumnSpacing="12">
|
||||
<Label Text="{Binding Name}" FontSize="20" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorText}" LineBreakMode="TailTruncation" />
|
||||
<Border Grid.Column="1" Style="{StaticResource UlStatusBadge}"
|
||||
BackgroundColor="{DynamicResource UlColorCanvas}"
|
||||
Stroke="{DynamicResource UlColorBorder}"
|
||||
StrokeShape="RoundRectangle 8" Padding="8,4">
|
||||
<Label Text="{Binding ActiveStatusLabel}" FontSize="14" FontAttributes="Bold"
|
||||
TextColor="{DynamicResource UlColorText}" />
|
||||
</Border>
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding JobSummary}"
|
||||
FontSize="16" TextColor="{DynamicResource UlColorTextMuted}" />
|
||||
<Grid Grid.Row="2" Grid.ColumnSpan="2" ColumnDefinitions="*,*" ColumnSpacing="8">
|
||||
<Button Style="{StaticResource UlButtonSecondary}"
|
||||
Text="{Binding ActiveActionLabel}"
|
||||
IsEnabled="{Binding IsActive, Converter={StaticResource InvertBool}}"
|
||||
Command="{Binding SetActiveCommand, Source={RelativeSource AncestorType={x:Type vm:JobsViewModel}}}"
|
||||
CommandParameter="{Binding .}" MinimumHeightRequest="{StaticResource UlTouchMinimum}"
|
||||
SemanticProperties.Description="{Binding ActiveActionDescription}" />
|
||||
<Button Grid.Column="1" Style="{StaticResource UlButtonAccent}"
|
||||
Text="Delete job"
|
||||
BackgroundColor="{DynamicResource UlColorAccent}"
|
||||
TextColor="{DynamicResource UlColorOnAccent}"
|
||||
Command="{Binding DeleteCommand, Source={RelativeSource AncestorType={x:Type vm:JobsViewModel}}}"
|
||||
CommandParameter="{Binding .}" MinimumHeightRequest="{StaticResource UlTouchMinimum}"
|
||||
SemanticProperties.Description="{Binding DeleteDescription}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
</RefreshView>
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
|
||||
@@ -4,10 +4,32 @@
|
||||
xmlns:vm="clr-namespace:FieldLogger.ViewModels"
|
||||
x:Class="FieldLogger.Views.MapPage"
|
||||
x:DataType="vm:MapViewModel"
|
||||
Title="Map">
|
||||
Title="Map"
|
||||
BackgroundColor="{DynamicResource UlColorMap}">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Label Grid.Row="0" Text="{Binding StatusText}" FontSize="12" TextColor="Gray" Padding="12,6" />
|
||||
<Border Style="{StaticResource UlCard}" Margin="12" Padding="16" BackgroundColor="{DynamicResource UlColorSurfaceRaised}"
|
||||
Stroke="{DynamicResource UlColorBorder}" StrokeShape="RoundRectangle 12"
|
||||
ZIndex="1">
|
||||
<Grid RowDefinitions="Auto,Auto" ColumnDefinitions="*,Auto" RowSpacing="4" ColumnSpacing="12">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="LIVE MAP" FontSize="14" FontAttributes="Bold" CharacterSpacing="1.5"
|
||||
TextColor="{DynamicResource UlColorPrimary}" />
|
||||
<Label Text="{Binding JobName, TargetNullValue='No active job'}"
|
||||
Style="{StaticResource UlSectionTitle}" TextColor="{DynamicResource UlColorText}"
|
||||
SemanticProperties.HeadingLevel="Level1" />
|
||||
</VerticalStackLayout>
|
||||
<Button Grid.Column="1" Style="{StaticResource UlButtonSecondary}"
|
||||
Text="Refresh" Clicked="OnRefreshClicked"
|
||||
MinimumHeightRequest="{StaticResource UlTouchMinimum}" MinimumWidthRequest="88"
|
||||
SemanticProperties.Description="Refresh captured points on the map" />
|
||||
<Label Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding StatusText}" FontSize="14"
|
||||
TextColor="{DynamicResource UlColorTextMuted}"
|
||||
SemanticProperties.Description="Current map data status" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- Populated in code-behind: native Map control on iOS/Android/macOS, Google Maps WebView on Windows. -->
|
||||
<ContentView Grid.Row="1" x:Name="MapHost" />
|
||||
<ContentView Grid.RowSpan="2" x:Name="MapHost"
|
||||
BackgroundColor="{DynamicResource UlColorMap}"
|
||||
SemanticProperties.Description="Map of locally captured points for the selected job" />
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
|
||||
@@ -32,6 +32,16 @@ public partial class MapPage : ContentPage
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
await RefreshMapAsync();
|
||||
}
|
||||
|
||||
private async void OnRefreshClicked(object? sender, EventArgs e)
|
||||
{
|
||||
await RefreshMapAsync();
|
||||
}
|
||||
|
||||
private async Task RefreshMapAsync()
|
||||
{
|
||||
await EnsureMapCreatedAsync();
|
||||
var points = await _viewModel.LoadPointsAsync();
|
||||
ShowPoints(points);
|
||||
|
||||
Reference in New Issue
Block a user