Initial commit: FieldLogger MAUI app with Maglink BLE support
Added Maglink RTK GNSS receiver integration with correct BLE UUIDs and device name filtering (ML-* prefix). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
104
FieldLogger/ViewModels/JobsViewModel.cs
Normal file
104
FieldLogger/ViewModels/JobsViewModel.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using FieldLogger.Models;
|
||||
using FieldLogger.Services;
|
||||
using FieldLogger.Services.Data;
|
||||
|
||||
namespace FieldLogger.ViewModels;
|
||||
|
||||
public sealed partial class JobListItem : ObservableObject
|
||||
{
|
||||
public required Job Job { get; init; }
|
||||
|
||||
[ObservableProperty]
|
||||
private int _pointCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isActive;
|
||||
|
||||
public string Name => Job.Name;
|
||||
public string CreatedLabel => Job.CreatedUtc.ToLocalTime().ToString("g");
|
||||
}
|
||||
|
||||
public sealed partial class JobsViewModel : ObservableObject
|
||||
{
|
||||
private readonly AppDatabase _database;
|
||||
private readonly SettingsService _settings;
|
||||
|
||||
public ObservableCollection<JobListItem> Jobs { get; } = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isBusy;
|
||||
|
||||
public JobsViewModel(AppDatabase database, SettingsService settings)
|
||||
{
|
||||
_database = database;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task RefreshAsync()
|
||||
{
|
||||
IsBusy = true;
|
||||
try
|
||||
{
|
||||
var jobs = await _database.GetJobsAsync();
|
||||
var activeId = _settings.ActiveJobId;
|
||||
|
||||
Jobs.Clear();
|
||||
foreach (var job in jobs)
|
||||
{
|
||||
Jobs.Add(new JobListItem
|
||||
{
|
||||
Job = job,
|
||||
PointCount = await _database.GetPointCountAsync(job.Id),
|
||||
IsActive = job.Id == activeId,
|
||||
});
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task NewJobAsync()
|
||||
{
|
||||
var name = await Shell.Current.DisplayPromptAsync("New Job", "Job name:",
|
||||
placeholder: $"Job {DateTime.Now:yyyy-MM-dd}");
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return;
|
||||
|
||||
var job = await _database.CreateJobAsync(name.Trim());
|
||||
_settings.ActiveJobId = job.Id;
|
||||
await RefreshAsync();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SetActiveAsync(JobListItem item)
|
||||
{
|
||||
_settings.ActiveJobId = item.Job.Id;
|
||||
foreach (var j in Jobs)
|
||||
j.IsActive = j.Job.Id == item.Job.Id;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private Task OpenAsync(JobListItem item)
|
||||
=> Shell.Current.GoToAsync($"jobdetail?jobId={item.Job.Id}");
|
||||
|
||||
[RelayCommand]
|
||||
private async Task DeleteAsync(JobListItem item)
|
||||
{
|
||||
var confirmed = await Shell.Current.DisplayAlert("Delete Job",
|
||||
$"Delete \"{item.Job.Name}\" and its {item.PointCount} logged points?", "Delete", "Cancel");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
await _database.DeleteJobAsync(item.Job.Id);
|
||||
if (_settings.ActiveJobId == item.Job.Id)
|
||||
_settings.ActiveJobId = null;
|
||||
await RefreshAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user